├── .DS_Store ├── .gitignore ├── Classes ├── AppController.h ├── AppController.m ├── BrowserViewController.h ├── BrowserViewController.m ├── CommitDetailViewController.h ├── CommitDetailViewController.m ├── CommitsViewController.h ├── CommitsViewController.m ├── ProjectController.h ├── ProjectController.m ├── ProjectDetailViewController.h ├── ProjectDetailViewController.m ├── ProjectViewController.h ├── ProjectViewController.m ├── ServerViewController.h └── ServerViewController.m ├── Client ├── ASIAuthenticationDialog.h ├── ASIAuthenticationDialog.m ├── ASIFormDataRequest.h ├── ASIFormDataRequest.m ├── ASIHTTPRequest.h ├── ASIHTTPRequest.m ├── ASIHTTPRequestConfig.h ├── ASIInputStream.h ├── ASIInputStream.m ├── ASINSStringAdditions.h ├── ASINSStringAdditions.m ├── ASINetworkQueue.h ├── ASINetworkQueue.m ├── Reachability.h └── Reachability.m ├── CocoaGit ├── Core │ ├── GITBlob.h │ ├── GITBlob.m │ ├── GITCommit.h │ ├── GITCommit.m │ ├── GITObject+Parsing.h │ ├── GITObject+Parsing.m │ ├── GITObject.h │ ├── GITObject.m │ ├── GITTag.h │ ├── GITTag.m │ ├── GITTree.h │ ├── GITTree.m │ ├── GITTreeEntry.h │ └── GITTreeEntry.m ├── Extra │ ├── GITActor.h │ ├── GITActor.m │ ├── GITDateTime.h │ ├── GITDateTime.m │ ├── GITErrors.h │ ├── GITErrors.m │ ├── GITUtilityBelt.h │ └── GITUtilityBelt.m ├── GITRepo.h ├── GITRepo.m ├── Git.h ├── Graph │ ├── GITCommitEnumerator.h │ ├── GITCommitEnumerator.m │ ├── GITGraph.h │ ├── GITGraph.m │ ├── GITNode.h │ ├── GITNode.m │ ├── GITRepo+Enumerators.h │ └── GITRepo+Enumerators.m ├── Pack │ ├── GITPackFile.h │ ├── GITPackFile.m │ ├── GITPackFileVersion2.h │ ├── GITPackFileVersion2.m │ ├── GITPackIndex.h │ ├── GITPackIndex.m │ ├── GITPackIndexVersion1.h │ ├── GITPackIndexVersion1.m │ ├── GITPackIndexVersion2.h │ ├── GITPackIndexVersion2.m │ ├── GITPackReverseIndex.h │ ├── GITPackReverseIndex.m │ ├── GITPlaceholderPackFile.h │ ├── GITPlaceholderPackFile.m │ ├── GITPlaceholderPackIndex.h │ └── GITPlaceholderPackIndex.m ├── Refs │ ├── GITBranch.h │ ├── GITBranch.m │ ├── GITRef.h │ └── GITRef.m ├── Store │ ├── GITCombinedStore.h │ ├── GITCombinedStore.m │ ├── GITFileStore.h │ ├── GITFileStore.m │ ├── GITObjectStore.h │ ├── GITObjectStore.m │ ├── GITPackStore.h │ ├── GITPackStore.m │ ├── GITRefStore.h │ └── GITRefStore.m └── Util │ ├── NSCharacterSet+StringComparison.h │ ├── NSCharacterSet+StringComparison.m │ ├── NSData+Compression.h │ ├── NSData+Compression.m │ ├── NSData+Hashing.h │ ├── NSData+Hashing.m │ ├── NSData+HexDump.h │ ├── NSData+HexDump.m │ ├── NSData+Patching.h │ ├── NSData+Patching.m │ ├── NSData+Searching.h │ ├── NSData+Searching.m │ ├── NSError-OBExtensions.h │ ├── NSError-OBExtensions.m │ ├── NSFileManager+DirHelper.h │ ├── NSFileManager+DirHelper.m │ ├── NSTimeZone+Offset.h │ ├── NSTimeZone+Offset.m │ ├── assertions.h │ └── assertions.m ├── Controllers ├── AppController.h ├── AppController.m ├── BrowserViewController.h ├── BrowserViewController.m ├── CommitDetailViewController.h ├── CommitDetailViewController.m ├── CommitsViewController.h ├── CommitsViewController.m ├── GitHTTPConnection.h ├── GitHTTPConnection.m ├── ProjectController.h ├── ProjectController.m ├── ProjectDetailViewController.h ├── ProjectDetailViewController.m ├── ProjectViewController.h ├── ProjectViewController.m ├── ServerViewController.h └── ServerViewController.m ├── Git ├── ObjGit.h ├── ObjGit.m ├── ObjGitCommit.h ├── ObjGitCommit.m ├── ObjGitObject.h ├── ObjGitObject.m ├── ObjGitServerHandler.h ├── ObjGitServerHandler.m ├── ObjGitTest.h ├── ObjGitTest.m ├── ObjGitTree.h ├── ObjGitTree.m └── runTests.m ├── Http ├── AsyncSocket.h ├── AsyncSocket.m ├── DDData.h ├── DDData.m ├── DDNumber.h ├── DDNumber.m ├── DDRange.h ├── DDRange.m ├── HTTPAuthenticationRequest.h ├── HTTPAuthenticationRequest.m ├── HTTPConnection.h ├── HTTPConnection.m ├── HTTPResponse.h ├── HTTPResponse.m ├── HTTPServer.h └── HTTPServer.m ├── Info.plist ├── LICENSE ├── Prefix.pch ├── TODO ├── assets ├── Default.png ├── bg.png ├── icon.png ├── octocat.png ├── rssicon.png ├── server.png ├── servericon.png └── test.png ├── http-protocol.txt ├── iGitHub.xcodeproj └── project.pbxproj └── main.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/* 2 | iGitHub.xcodeproj/schacon.* 3 | 4 | -------------------------------------------------------------------------------- /Classes/AppController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: AppController.h 4 | Abstract: UIApplication's delegate class, the central controller of the 5 | application. 6 | 7 | Version: 1.5 8 | 9 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 10 | ("Apple") in consideration of your agreement to the following terms, and your 11 | use, installation, modification or redistribution of this Apple software 12 | constitutes acceptance of these terms. If you do not agree with these terms, 13 | please do not use, install, modify or redistribute this Apple software. 14 | 15 | In consideration of your agreement to abide by the following terms, and subject 16 | to these terms, Apple grants you a personal, non-exclusive license, under 17 | Apple's copyrights in this original Apple software (the "Apple Software"), to 18 | use, reproduce, modify and redistribute the Apple Software, with or without 19 | modifications, in source and/or binary forms; provided that if you redistribute 20 | the Apple Software in its entirety and without modifications, you must retain 21 | this notice and the following text and disclaimers in all such redistributions 22 | of the Apple Software. 23 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 24 | to endorse or promote products derived from the Apple Software without specific 25 | prior written permission from Apple. Except as expressly stated in this notice, 26 | no other rights or licenses, express or implied, are granted by Apple herein, 27 | including but not limited to any patent rights that may be infringed by your 28 | derivative works or by other works in which the Apple Software may be 29 | incorporated. 30 | 31 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 32 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 33 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 35 | COMBINATION WITH YOUR PRODUCTS. 36 | 37 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 38 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 39 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 41 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 42 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 43 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | 45 | Copyright (C) 2008 Apple Inc. All Rights Reserved. 46 | 47 | */ 48 | 49 | #import "BrowserViewController.h" 50 | #import "ServerViewController.h" 51 | 52 | //CLASS INTERFACES: 53 | 54 | @interface AppController : NSObject 55 | { 56 | UIWindow* _window; 57 | UINavigationController *navigationController; 58 | UITabBarController *tabBarController; 59 | ServerViewController *serverViewController; 60 | NSString* gitDir; 61 | } 62 | 63 | @property (nonatomic, retain) UINavigationController *navigationController; 64 | @property (nonatomic, retain) UITabBarController *tabBarController; 65 | @property (nonatomic, retain) ServerViewController *serverViewController; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Classes/AppController.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: AppController.m 4 | Abstract: UIApplication's delegate class, the central controller of the 5 | application. 6 | 7 | Version: 1.5 8 | 9 | */ 10 | 11 | #import "AppController.h" 12 | #import "ProjectViewController.h" 13 | #import "ProjectController.h" 14 | #import "ServerViewController.h" 15 | 16 | #define bonIdentifier @"git" 17 | 18 | //INTERFACES: 19 | 20 | @interface AppController () 21 | 22 | @property (assign, readwrite) NSString *gitDir; 23 | 24 | - (void) setup; 25 | 26 | @end 27 | 28 | //CLASS IMPLEMENTATIONS: 29 | 30 | @implementation AppController 31 | 32 | @synthesize gitDir; 33 | @synthesize navigationController; 34 | @synthesize tabBarController; 35 | @synthesize serverViewController; 36 | 37 | - (NSString *)getGitPath 38 | { 39 | NSArray *paths; 40 | NSString *gitPath = @""; 41 | paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 42 | if ([paths count] > 0) { 43 | gitPath = [NSString stringWithString:[[paths objectAtIndex:0] stringByAppendingPathComponent:@"git"]]; 44 | 45 | BOOL isDir; 46 | NSFileManager *fm = [NSFileManager defaultManager]; 47 | if (![fm fileExistsAtPath:gitPath isDirectory:&isDir] && isDir) { 48 | [fm createDirectoryAtPath:gitPath attributes:nil]; 49 | } 50 | } 51 | return gitPath; 52 | } 53 | 54 | - (void) applicationDidFinishLaunching:(UIApplication*)application 55 | { 56 | NSString * thisHostName = [[NSProcessInfo processInfo] hostName]; 57 | NSLog(@"hostname: %@", thisHostName); 58 | // Create a full-screen window 59 | _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 60 | 61 | // getting the git path 62 | gitDir = [self getGitPath]; 63 | 64 | // Create and configure the navigation and view controllers 65 | ProjectController *pController = [[ProjectController alloc] init]; 66 | [pController readProjects:gitDir]; 67 | 68 | ProjectViewController *projectViewController = [[ProjectViewController alloc] initWithStyle:UITableViewStylePlain]; 69 | [projectViewController setProjectController:pController]; 70 | 71 | ServerViewController *serverController = [[ServerViewController alloc] init]; 72 | self.serverViewController = serverController; 73 | 74 | UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:projectViewController]; 75 | self.navigationController = aNavigationController; 76 | 77 | UITabBarController *atabBarController = [[UITabBarController alloc] init]; 78 | NSArray *vc = [NSArray arrayWithObjects:navigationController, serverViewController, nil]; 79 | [atabBarController setViewControllers:vc animated:NO]; 80 | self.tabBarController = atabBarController; 81 | 82 | // Configure and show the window 83 | [_window addSubview:tabBarController.view]; 84 | [_window makeKeyAndVisible]; 85 | 86 | [projectViewController release]; 87 | [aNavigationController release]; 88 | 89 | [self setup]; 90 | } 91 | 92 | - (void) dealloc 93 | { 94 | NSLog(@"dealloc"); 95 | [_window release]; 96 | [super dealloc]; 97 | } 98 | 99 | - (void) setup { 100 | // TODO: setup the http server 101 | NSLog(@"Setup"); 102 | 103 | gitDir = [self getGitPath]; 104 | 105 | BOOL isDir=NO; 106 | NSFileManager *fileManager = [NSFileManager defaultManager]; 107 | if ([fileManager fileExistsAtPath:gitDir isDirectory:&isDir] && isDir) { 108 | NSEnumerator *e = [[fileManager directoryContentsAtPath:gitDir] objectEnumerator]; 109 | NSString *thisDir; 110 | while ( (thisDir = [e nextObject]) ) { 111 | NSLog(@"announce:%@", thisDir); 112 | // TODO: announce http over bonjour 113 | } 114 | } 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /Classes/BrowserViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: BrowserViewController.h 4 | Abstract: 5 | View controller for the service instance list. 6 | This object manages a NSNetServiceBrowser configured to look for Bonjour 7 | services. 8 | It has an array of NSNetService objects that are displayed in a table view. 9 | When the service browser reports that it has discovered a service, the 10 | corresponding NSNetService is added to the array. 11 | When a service goes away, the corresponding NSNetService is removed from the 12 | array. 13 | Selecting an item in the table view asynchronously resolves the corresponding 14 | net service. 15 | When that resolution completes, the delegate is called with the corresponding 16 | NSNetService. 17 | 18 | 19 | Version: 1.5 20 | 21 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 22 | ("Apple") in consideration of your agreement to the following terms, and your 23 | use, installation, modification or redistribution of this Apple software 24 | constitutes acceptance of these terms. If you do not agree with these terms, 25 | please do not use, install, modify or redistribute this Apple software. 26 | 27 | In consideration of your agreement to abide by the following terms, and subject 28 | to these terms, Apple grants you a personal, non-exclusive license, under 29 | Apple's copyrights in this original Apple software (the "Apple Software"), to 30 | use, reproduce, modify and redistribute the Apple Software, with or without 31 | modifications, in source and/or binary forms; provided that if you redistribute 32 | the Apple Software in its entirety and without modifications, you must retain 33 | this notice and the following text and disclaimers in all such redistributions 34 | of the Apple Software. 35 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 36 | to endorse or promote products derived from the Apple Software without specific 37 | prior written permission from Apple. Except as expressly stated in this notice, 38 | no other rights or licenses, express or implied, are granted by Apple herein, 39 | including but not limited to any patent rights that may be infringed by your 40 | derivative works or by other works in which the Apple Software may be 41 | incorporated. 42 | 43 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 44 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 45 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 47 | COMBINATION WITH YOUR PRODUCTS. 48 | 49 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 50 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 51 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 53 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 54 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 55 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | Copyright (C) 2008 Apple Inc. All Rights Reserved. 58 | 59 | */ 60 | 61 | #import 62 | #import 63 | 64 | @class BrowserViewController; 65 | 66 | @protocol BrowserViewControllerDelegate 67 | @required 68 | // This method will be invoked when the user selects one of the service instances from the list. 69 | // The ref parameter will be the selected (already resolved) instance or nil if the user taps the 'Cancel' button (if shown). 70 | - (void) browserViewController:(BrowserViewController*)bvc didResolveInstance:(NSNetService*)ref; 71 | @end 72 | 73 | @interface BrowserViewController : UITableViewController { 74 | 75 | @private 76 | id _delegate; 77 | NSString* _searchingForServicesString; 78 | NSString* _ownName; 79 | NSNetService* _ownEntry; 80 | BOOL _showDisclosureIndicators; 81 | NSMutableArray* _services; 82 | NSNetServiceBrowser* _netServiceBrowser; 83 | NSNetService* _currentResolve; 84 | NSTimer* _timer; 85 | BOOL _needsActivityIndicator; 86 | BOOL _initialWaitOver; 87 | } 88 | 89 | @property (nonatomic, assign) id delegate; 90 | @property (nonatomic, copy) NSString* searchingForServicesString; 91 | @property (nonatomic, copy) NSString* ownName; 92 | 93 | - (id)initWithTitle:(NSString *)title showDisclosureIndicators:(BOOL)showDisclosureIndicators showCancelButton:(BOOL)showCancelButton; 94 | - (BOOL)searchForServicesOfType:(NSString *)type inDomain:(NSString *)domain; 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /Classes/CommitDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommitDetailViewController.h 3 | // iGitHub 4 | // 5 | // Created by Scott Chacon on 9/29/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ObjGit.h" 11 | #import "ObjGitCommit.h" 12 | 13 | @interface CommitDetailViewController : UITableViewController { 14 | ObjGit *gitRepo; 15 | ObjGitCommit *gitCommit; 16 | } 17 | 18 | @property (nonatomic, retain) ObjGit *gitRepo; 19 | @property (nonatomic, retain) ObjGitCommit *gitCommit; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/CommitsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommitsViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "Git.h" 8 | 9 | @interface CommitsViewController : UITableViewController { 10 | GITRepo *gitRepo; 11 | NSString *gitRef; 12 | NSString *gitSha; 13 | NSMutableArray *commitList; 14 | } 15 | 16 | @property (nonatomic, retain) GITRepo *gitRepo; 17 | @property (nonatomic, retain) NSString *gitRef; 18 | @property (nonatomic, retain) NSString *gitSha; 19 | @property (nonatomic, retain) NSMutableArray *commitList; 20 | 21 | - (UITableViewCell *)tableviewCellWithReuseIdentifier:(NSString *)identifier; 22 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/ProjectController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | 8 | @interface ProjectController : NSObject { 9 | NSMutableArray *list; 10 | } 11 | 12 | - (void)readProjects:(NSString *)projectPath; 13 | - (unsigned)countOfList; 14 | - (id)objectInListAtIndex:(unsigned)theIndex; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/ProjectController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectController.h" 7 | #import "Git.h" 8 | 9 | @interface ProjectController () 10 | @property (nonatomic, copy, readwrite) NSMutableArray *list; 11 | @end 12 | 13 | @implementation ProjectController 14 | 15 | @synthesize list; 16 | 17 | // Custom set accessor to ensure the new list is mutable 18 | - (void)readProjects:(NSString *)projectPath 19 | { 20 | NSLog(@"READ PROJECTS:%@", projectPath); 21 | BOOL isDir=NO; 22 | [list release]; 23 | list = [[NSMutableArray alloc] init]; 24 | NSFileManager *fileManager = [NSFileManager defaultManager]; 25 | if ([fileManager fileExistsAtPath:projectPath isDirectory:&isDir] && isDir) { 26 | NSEnumerator *e = [[fileManager directoryContentsAtPath:projectPath] objectEnumerator]; 27 | NSString *thisDir; 28 | while ( (thisDir = [e nextObject]) ) { 29 | NSString *dir = [projectPath stringByAppendingPathComponent:thisDir]; 30 | GITRepo* git = [[GITRepo alloc] init]; 31 | [git initWithRoot:dir]; 32 | [git setDesc:thisDir]; 33 | [list addObject:git]; 34 | } 35 | } 36 | } 37 | 38 | // Accessor methods for list 39 | - (unsigned)countOfList { 40 | return [list count]; 41 | } 42 | 43 | - (id)objectInListAtIndex:(unsigned)theIndex { 44 | return [list objectAtIndex:theIndex]; 45 | } 46 | 47 | - (void)dealloc { 48 | [list release]; 49 | [super dealloc]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Classes/ProjectDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectDetailViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "Git.h" 8 | 9 | @interface ProjectDetailViewController : UITableViewController { 10 | GITRepo *detailItem; 11 | } 12 | 13 | @property (nonatomic, retain) GITRepo *detailItem; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/ProjectDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectDetailViewController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectDetailViewController.h" 7 | #import "CommitsViewController.h" 8 | #import "Git.h" 9 | 10 | @implementation ProjectDetailViewController 11 | 12 | @synthesize detailItem; 13 | 14 | 15 | - (void)viewWillAppear:(BOOL)animated { 16 | // Update the view with current data before it is displayed 17 | [super viewWillAppear:animated]; 18 | 19 | // Scroll the table view to the top before it appears 20 | [self.tableView reloadData]; 21 | [self.tableView setContentOffset:CGPointZero animated:NO]; 22 | self.title = [detailItem desc]; 23 | } 24 | 25 | // Standard table view data source and delegate methods 26 | 27 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 28 | // There are two sections, for info and stats 29 | return 2; 30 | } 31 | 32 | 33 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 34 | 35 | NSInteger rows = 0; 36 | switch (section) { 37 | case 0: 38 | // For project data, there is name 39 | rows = 1; 40 | break; 41 | case 1: 42 | // For the branches section, there is size 43 | rows = [[detailItem branches] count]; 44 | break; 45 | default: 46 | break; 47 | } 48 | return rows; 49 | } 50 | 51 | 52 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 53 | 54 | static NSString *CellIdentifier = @"tvc"; 55 | 56 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 57 | if (cell == nil) { 58 | cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; 59 | //cell.selectionStyle = UITableViewCellSelectionStyleNone; 60 | } 61 | 62 | NSString *cellText = nil; 63 | 64 | switch (indexPath.section) { 65 | case 0: 66 | cellText = [detailItem desc]; 67 | break; 68 | case 1: 69 | cellText = [[[detailItem branches] objectAtIndex:indexPath.row] objectAtIndex:0]; 70 | 71 | break; 72 | default: 73 | break; 74 | } 75 | 76 | cell.text = cellText; 77 | return cell; 78 | } 79 | 80 | 81 | /* 82 | Provide section titles 83 | HIG note: In this case, since the content of each section is obvious, there's probably no need to provide a title, but the code is useful for illustration. 84 | */ 85 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 86 | 87 | NSString *title = nil; 88 | switch (section) { 89 | case 0: 90 | title = NSLocalizedString(@"Project Info", @"Git Project Information"); 91 | break; 92 | case 1: 93 | title = NSLocalizedString(@"Branches", @"Git Project Refs"); 94 | break; 95 | default: 96 | break; 97 | } 98 | return title; 99 | } 100 | 101 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 102 | CommitsViewController *commitsViewController = [[CommitsViewController alloc] initWithStyle:UITableViewStylePlain]; 103 | NSArray *refArray = [[detailItem branches] objectAtIndex:indexPath.row]; 104 | NSLog(@"refs:%@", refArray); 105 | 106 | commitsViewController.gitRepo = detailItem; 107 | commitsViewController.gitRef = [refArray objectAtIndex:0]; 108 | commitsViewController.gitSha = [refArray objectAtIndex:1]; 109 | 110 | NSLog(@"TEST"); 111 | 112 | // Push the commit view controller 113 | [[self navigationController] pushViewController:commitsViewController animated:YES]; 114 | [commitsViewController release]; 115 | } 116 | 117 | @end 118 | -------------------------------------------------------------------------------- /Classes/ProjectViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "ProjectController.h" 8 | #import "Git.h" 9 | 10 | @interface ProjectViewController : UITableViewController { 11 | ProjectController *projectController; 12 | } 13 | 14 | @property (nonatomic, retain) ProjectController *projectController; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Classes/ProjectViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectViewController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectViewController.h" 7 | #import "ProjectDetailViewController.h" 8 | 9 | @implementation ProjectViewController 10 | 11 | @synthesize projectController; 12 | 13 | - (id)initWithStyle:(UITableViewStyle)style { 14 | if ((self = [super initWithStyle:style])) { 15 | self.title = NSLocalizedString(@"Projects", @"My Local Git Project List"); 16 | self.tabBarItem.image = [UIImage imageNamed:@"servericon.png"]; 17 | } 18 | return self; 19 | } 20 | 21 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 22 | return 1; 23 | } 24 | 25 | 26 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 27 | return [projectController countOfList]; 28 | } 29 | 30 | 31 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 32 | 33 | static NSString *MyIdentifier = @"MyIdentifier"; 34 | 35 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 36 | if (cell == nil) { 37 | cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease]; 38 | } 39 | 40 | // Get the object to display and set the value in the cell 41 | GITRepo *itemAtIndex = [projectController objectInListAtIndex:indexPath.row]; 42 | cell.text = [itemAtIndex desc]; 43 | return cell; 44 | } 45 | 46 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 47 | 48 | ProjectDetailViewController *detailViewController = [[ProjectDetailViewController alloc] initWithStyle:UITableViewStyleGrouped]; 49 | detailViewController.detailItem = [projectController objectInListAtIndex:indexPath.row]; 50 | 51 | // Push the detail view controller 52 | [[self navigationController] pushViewController:detailViewController animated:YES]; 53 | [detailViewController release]; 54 | } 55 | 56 | /* 57 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 58 | 59 | if (editingStyle == UITableViewCellEditingStyleDelete) { 60 | } 61 | if (editingStyle == UITableViewCellEditingStyleInsert) { 62 | } 63 | } 64 | */ 65 | /* 66 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 67 | return YES; 68 | } 69 | */ 70 | /* 71 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 72 | } 73 | */ 74 | /* 75 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 76 | return YES; 77 | } 78 | */ 79 | 80 | 81 | - (void)dealloc { 82 | [super dealloc]; 83 | } 84 | 85 | 86 | - (void)viewDidLoad { 87 | [super viewDidLoad]; 88 | } 89 | 90 | 91 | - (void)viewWillAppear:(BOOL)animated { 92 | [super viewWillAppear:animated]; 93 | } 94 | 95 | - (void)viewDidAppear:(BOOL)animated { 96 | [super viewDidAppear:animated]; 97 | } 98 | 99 | - (void)viewWillDisappear:(BOOL)animated { 100 | } 101 | 102 | - (void)viewDidDisappear:(BOOL)animated { 103 | } 104 | 105 | - (void)didReceiveMemoryWarning { 106 | [super didReceiveMemoryWarning]; 107 | } 108 | 109 | 110 | @end 111 | 112 | -------------------------------------------------------------------------------- /Classes/ServerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServerViewController.h 3 | // iGitHub 4 | // 5 | // Created by Scott Chacon on 9/30/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface ServerViewController : UIViewController { 13 | UILabel* serverNameLabel; 14 | } 15 | 16 | @property (nonatomic, retain) UILabel* serverNameLabel; 17 | 18 | - (void)setServerName:(NSString *)string; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Classes/ServerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerViewController.m 3 | // iGitHub 4 | // 5 | 6 | 7 | #import "ServerViewController.h" 8 | 9 | #define kOffset 5.0 10 | 11 | @implementation ServerViewController 12 | 13 | @synthesize serverNameLabel; 14 | 15 | -(id)init { 16 | self = [super init]; 17 | if (self) { 18 | self.title = @"Server"; 19 | self.tabBarItem.image = [UIImage imageNamed:@"rssicon.png"]; 20 | } 21 | return self; 22 | } 23 | 24 | -(void)loadView { 25 | NSLog(@"First View"); 26 | UIView *firstView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"server.png"]]; 27 | [firstView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth]; 28 | [firstView setBackgroundColor:[UIColor yellowColor]]; 29 | self.view = firstView; 30 | [firstView release]; 31 | 32 | UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; 33 | [label setTextAlignment:UITextAlignmentCenter]; 34 | [label setFont:[UIFont systemFontOfSize:18.0]]; 35 | [label setTextColor:[UIColor blackColor]]; 36 | [label setBackgroundColor:[UIColor clearColor]]; 37 | label.text = @"Git Server Listening On"; 38 | label.numberOfLines = 1; 39 | [label sizeToFit]; 40 | label.frame = CGRectMake(0.0, 200.0, 320.0, label.frame.size.height); 41 | [self.view addSubview:label]; 42 | 43 | NSString *hostName = [[NSProcessInfo processInfo] hostName]; 44 | if ([hostName hasSuffix:@".local"]) { 45 | hostName = [hostName substringToIndex:([hostName length] - 6)]; 46 | } 47 | label = [[UILabel alloc] initWithFrame:CGRectZero]; 48 | [label setTextAlignment:UITextAlignmentCenter]; 49 | [label setFont:[UIFont systemFontOfSize:28.0]]; 50 | [label setTextColor:[UIColor blackColor]]; 51 | [label setBackgroundColor:[UIColor clearColor]]; 52 | label.text = [NSString stringWithFormat:@"git://%@/", hostName]; 53 | label.numberOfLines = 1; 54 | [label sizeToFit]; 55 | label.frame = CGRectMake(0.0, 250.0, 320.0, label.frame.size.height); 56 | self.serverNameLabel = label; 57 | [self.view addSubview:self.serverNameLabel]; 58 | } 59 | 60 | - (void)setServerName:(NSString *)string { 61 | [self.serverNameLabel setText:string]; 62 | } 63 | 64 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 65 | // Return YES for supported orientations 66 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 67 | } 68 | 69 | 70 | - (void)didReceiveMemoryWarning { 71 | [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview 72 | // Release anything that's not essential, such as cached data 73 | } 74 | 75 | 76 | - (void)dealloc { 77 | [super dealloc]; 78 | } 79 | 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Client/ASIAuthenticationDialog.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIAuthenticationDialog.h 3 | // iPhone 4 | // 5 | // Created by Ben Copsey on 21/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | @class ASIHTTPRequest; 11 | 12 | typedef enum _ASIAuthenticationType { 13 | ASIStandardAuthenticationType = 0, 14 | ASIProxyAuthenticationType = 1 15 | } ASIAuthenticationType; 16 | 17 | @interface ASIAuthenticationDialog : NSObject { 18 | ASIHTTPRequest *request; 19 | UIActionSheet *loginDialog; 20 | ASIAuthenticationType type; 21 | } 22 | + (void)presentAuthenticationDialogForRequest:(ASIHTTPRequest *)request; 23 | + (void)presentProxyAuthenticationDialogForRequest:(ASIHTTPRequest *)request; 24 | 25 | @property (retain) ASIHTTPRequest *request; 26 | @property (retain) UIActionSheet *loginDialog; 27 | @property (assign) ASIAuthenticationType type; 28 | @end 29 | -------------------------------------------------------------------------------- /Client/ASIFormDataRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIFormDataRequest.h 3 | // asi-http-request 4 | // 5 | // Created by Ben Copsey on 07/11/2008. 6 | // Copyright 2008-2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ASIHTTPRequest.h" 11 | #import "ASIHTTPRequestConfig.h" 12 | 13 | typedef enum _ASIPostFormat { 14 | ASIMultipartFormDataPostFormat = 0, 15 | ASIURLEncodedPostFormat = 1 16 | 17 | } ASIPostFormat; 18 | 19 | @interface ASIFormDataRequest : ASIHTTPRequest { 20 | 21 | // Parameters that will be POSTed to the url 22 | NSMutableDictionary *postData; 23 | 24 | // Files that will be POSTed to the url 25 | NSMutableDictionary *fileData; 26 | 27 | ASIPostFormat postFormat; 28 | 29 | NSStringEncoding stringEncoding; 30 | 31 | #if ASIHTTPREQUEST_DEBUG 32 | // Will store a string version of the request body that will be printed to the console when ASIHTTPREQUEST_DEBUG is set in GCC_PREPROCESSOR_DEFINITIONS 33 | NSString *debugBodyString; 34 | #endif 35 | 36 | } 37 | 38 | #pragma mark utilities 39 | - (NSString*)encodeURL:(NSString *)string; 40 | 41 | #pragma mark setup request 42 | 43 | // Add a POST variable to the request 44 | - (void)setPostValue:(id )value forKey:(NSString *)key; 45 | 46 | // Add the contents of a local file to the request 47 | - (void)setFile:(NSString *)filePath forKey:(NSString *)key; 48 | 49 | // Same as above, but you can specify the content-type and file name 50 | - (void)setFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 51 | 52 | // Add the contents of an NSData object to the request 53 | - (void)setData:(NSData *)data forKey:(NSString *)key; 54 | 55 | // Same as above, but you can specify the content-type and file name 56 | - (void)setData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 57 | 58 | 59 | @property (assign) ASIPostFormat postFormat; 60 | @property (assign) NSStringEncoding stringEncoding; 61 | @end 62 | -------------------------------------------------------------------------------- /Client/ASIHTTPRequestConfig.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIHTTPRequestConfig.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 14/12/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | 10 | 11 | /* 12 | ASIHTTPRequest uses Apple's Reachability class (http://developer.apple.com/iphone/library/samplecode/Reachability/) to turn bandwidth throttling on and off automatically when shouldThrottleBandwidthForWWAN is set to YES on iPhone OS 13 | 14 | There are two versions of Apple's Reachability class, both of which are included in the source distribution of ASIHTTPRequest in the External/Reachability folder. 15 | 16 | * Version 2.0 is the latest version. You should use this if you are targeting iPhone OS 3.x and later 17 | To use Version 2.0, set this to 1, and include Reachbility.h + Reachbility.m from the Reachability 2.0 folder in your project 18 | 19 | * Version 1.5 is the old version, but it is compatible with both iPhone OS 2.2.1 and iPhone OS 3.0 and later. You should use this if your application needs to work on iPhone OS 2.2.1. 20 | To use Version 1.5, set this to 0, and include Reachbility.h + Reachbility.m from the Reachability 1.5 folder in your project 21 | 22 | This config option is not used for apps targeting Mac OS X 23 | */ 24 | 25 | #define REACHABILITY_20_API 0 26 | 27 | 28 | // When set to 1, requests will print debug information to the console (currently only used by ASIFormDataRequest) 29 | #define ASIHTTPREQUEST_DEBUG 1 -------------------------------------------------------------------------------- /Client/ASIInputStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIInputStream.h 3 | // asi-http-request 4 | // 5 | // Created by Ben Copsey on 10/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // This is a wrapper for NSInputStream that pretends to be an NSInputStream itself 12 | // Subclassing NSInputStream seems to be tricky, and may involve overriding undocumented methods, so we'll cheat instead. 13 | // It is used by ASIHTTPRequest whenever we have a request body, and handles measuring and throttling the bandwidth used for uploading 14 | 15 | @interface ASIInputStream : NSObject { 16 | NSInputStream *stream; 17 | } 18 | + (id)inputStreamWithFileAtPath:(NSString *)path; 19 | + (id)inputStreamWithData:(NSData *)data; 20 | 21 | @property (retain) NSInputStream *stream; 22 | @end 23 | -------------------------------------------------------------------------------- /Client/ASIInputStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASIInputStream.m 3 | // asi-http-request 4 | // 5 | // Created by Ben Copsey on 10/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import "ASIInputStream.h" 10 | #import "ASIHTTPRequest.h" 11 | 12 | // Used to ensure only one request can read data at once 13 | static NSLock *readLock = nil; 14 | 15 | @implementation ASIInputStream 16 | 17 | + (void)initialize 18 | { 19 | if (self == [ASIInputStream class]) { 20 | readLock = [[NSLock alloc] init]; 21 | } 22 | } 23 | 24 | + (id)inputStreamWithFileAtPath:(NSString *)path 25 | { 26 | ASIInputStream *stream = [[[self alloc] init] autorelease]; 27 | [stream setStream:[NSInputStream inputStreamWithFileAtPath:path]]; 28 | return stream; 29 | } 30 | 31 | + (id)inputStreamWithData:(NSData *)data 32 | { 33 | ASIInputStream *stream = [[[self alloc] init] autorelease]; 34 | [stream setStream:[NSInputStream inputStreamWithData:data]]; 35 | return stream; 36 | } 37 | 38 | - (void)dealloc 39 | { 40 | [stream release]; 41 | [super dealloc]; 42 | } 43 | 44 | 45 | // Ok, so this works, but I don't really understand why. 46 | // Ideally, we'd just return the stream's hasBytesAvailable, but CFNetwork seems to want to monopolise our run loop until (presumably) its buffer is full, which will cause timeouts if we're throttling the bandwidth 47 | // We return NO when we shouldn't be uploading any more data because our bandwidth limit has run out (for now) 48 | // The call to maxUploadReadLength will recognise that we've run out of our allotted bandwidth limit, and sleep this thread for the rest of the measurement period 49 | // This method will be called again, but we'll almost certainly return YES the next time around, because we'll have more limit to use up 50 | // The NO returns seem to snap CFNetwork out of its reverie, and return control to the main loop in loadRequest, so that we can manage timeouts and progress delegate updates 51 | - (BOOL)hasBytesAvailable 52 | { 53 | 54 | if ([ASIHTTPRequest isBandwidthThrottled]) { 55 | [readLock lock]; 56 | if ([ASIHTTPRequest maxUploadReadLength] == 0) { 57 | [readLock unlock]; 58 | return NO; 59 | } 60 | [readLock unlock]; 61 | } 62 | return [[self stream] hasBytesAvailable]; 63 | 64 | } 65 | 66 | // Called when CFNetwork wants to read more of our request body 67 | // When throttling is on, we ask ASIHTTPRequest for the maximum amount of data we can read 68 | - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len 69 | { 70 | [readLock lock]; 71 | unsigned long toRead = len; 72 | if ([ASIHTTPRequest isBandwidthThrottled]) { 73 | toRead = [ASIHTTPRequest maxUploadReadLength]; 74 | if (toRead > len) { 75 | toRead = len; 76 | 77 | // Hopefully this won't happen because hasBytesAvailable will have returned NO, but just in case - we need to read at least 1 byte, or bad things might happen 78 | } else if (toRead == 0) { 79 | toRead = 1; 80 | } 81 | //NSLog(@"Throttled read %u",toRead); 82 | } else { 83 | //NSLog(@"Unthrottled read %u",toRead); 84 | } 85 | [ASIHTTPRequest incrementBandwidthUsedInLastSecond:toRead]; 86 | [readLock unlock]; 87 | return [[self stream] read:buffer maxLength:toRead]; 88 | } 89 | 90 | // If we get asked to perform a method we don't have (which is almost all of them), we'll just forward the message to our stream 91 | 92 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 93 | { 94 | return [[self stream] methodSignatureForSelector:aSelector]; 95 | } 96 | 97 | - (void)forwardInvocation:(NSInvocation *)anInvocation 98 | { 99 | [anInvocation invokeWithTarget:[self stream]]; 100 | } 101 | 102 | @synthesize stream; 103 | @end 104 | -------------------------------------------------------------------------------- /Client/ASINSStringAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASINSStringAdditions.h 3 | // asi-http-request 4 | // 5 | // Created by Ben Copsey on 12/09/2008. 6 | // Copyright 2008 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (CookieValueEncodingAdditions) 12 | 13 | - (NSString *)encodedCookieValue; 14 | - (NSString *)decodedCookieValue; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Client/ASINSStringAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASINSStringAdditions.m 3 | // asi-http-request 4 | // 5 | // Created by Ben Copsey on 12/09/2008. 6 | // Copyright 2008 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import "ASINSStringAdditions.h" 10 | 11 | @implementation NSString (CookieValueEncodingAdditions) 12 | 13 | - (NSString *)decodedCookieValue 14 | { 15 | NSMutableString *s = [NSMutableString stringWithString:[self stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; 16 | //Also swap plus signs for spaces 17 | [s replaceOccurrencesOfString:@"+" withString:@" " options:NSLiteralSearch range:NSMakeRange(0, [s length])]; 18 | return [NSString stringWithString:s]; 19 | } 20 | 21 | - (NSString *)encodedCookieValue 22 | { 23 | return [self stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 24 | } 25 | 26 | @end 27 | 28 | 29 | -------------------------------------------------------------------------------- /Client/Reachability.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: Reachability.h 4 | Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. 5 | 6 | Version: 2.0 7 | 8 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 9 | ("Apple") in consideration of your agreement to the following terms, and your 10 | use, installation, modification or redistribution of this Apple software 11 | constitutes acceptance of these terms. If you do not agree with these terms, 12 | please do not use, install, modify or redistribute this Apple software. 13 | 14 | In consideration of your agreement to abide by the following terms, and subject 15 | to these terms, Apple grants you a personal, non-exclusive license, under 16 | Apple's copyrights in this original Apple software (the "Apple Software"), to 17 | use, reproduce, modify and redistribute the Apple Software, with or without 18 | modifications, in source and/or binary forms; provided that if you redistribute 19 | the Apple Software in its entirety and without modifications, you must retain 20 | this notice and the following text and disclaimers in all such redistributions 21 | of the Apple Software. 22 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 23 | to endorse or promote products derived from the Apple Software without specific 24 | prior written permission from Apple. Except as expressly stated in this notice, 25 | no other rights or licenses, express or implied, are granted by Apple herein, 26 | including but not limited to any patent rights that may be infringed by your 27 | derivative works or by other works in which the Apple Software may be 28 | incorporated. 29 | 30 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 31 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 32 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 33 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 34 | COMBINATION WITH YOUR PRODUCTS. 35 | 36 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 37 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 38 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 40 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 41 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 42 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 43 | 44 | Copyright (C) 2009 Apple Inc. All Rights Reserved. 45 | 46 | */ 47 | 48 | 49 | #import 50 | #import 51 | 52 | typedef enum { 53 | NotReachable = 0, 54 | ReachableViaWiFi, 55 | ReachableViaWWAN 56 | } NetworkStatus; 57 | #define kReachabilityChangedNotification @"kNetworkReachabilityChangedNotification" 58 | 59 | @interface Reachability: NSObject 60 | { 61 | BOOL localWiFiRef; 62 | SCNetworkReachabilityRef reachabilityRef; 63 | } 64 | 65 | //reachabilityWithHostName- Use to check the reachability of a particular host name. 66 | + (Reachability*) reachabilityWithHostName: (NSString*) hostName; 67 | 68 | //reachabilityWithAddress- Use to check the reachability of a particular IP address. 69 | + (Reachability*) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; 70 | 71 | //reachabilityForInternetConnection- checks whether the default route is available. 72 | // Should be used by applications that do not connect to a particular host 73 | + (Reachability*) reachabilityForInternetConnection; 74 | 75 | //reachabilityForLocalWiFi- checks whether a local wifi connection is available. 76 | + (Reachability*) reachabilityForLocalWiFi; 77 | 78 | //Start listening for reachability notifications on the current run loop 79 | - (BOOL) startNotifer; 80 | - (void) stopNotifer; 81 | 82 | - (NetworkStatus) currentReachabilityStatus; 83 | //WWAN may be available, but not active until a connection has been established. 84 | //WiFi may require a connection for VPN on Demand. 85 | - (BOOL) connectionRequired; 86 | @end 87 | 88 | 89 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITBlob.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITBlob.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObject.h" 11 | 12 | extern NSString * const kGITObjectBlobName; 13 | 14 | /*! Git object type representing a file. 15 | */ 16 | @interface GITBlob : GITObject 17 | { 18 | NSData * data; //!< The binary data of this blob 19 | } 20 | 21 | @property(readonly,copy) NSData * data; 22 | 23 | /*! Returns flag indicating probability that data is textual. 24 | * It is important to note that this indicates only the probability 25 | * that the receiver's data is textual. The indication is based on 26 | * the presence, or lack, of a NULL byte in the receivers 27 | * data. 28 | * \return Flag indicating probability that data is textual. 29 | */ 30 | - (BOOL)canBeRepresentedAsString; 31 | 32 | /*! Returns string contents of data. 33 | * \return String contents of data. 34 | */ 35 | - (NSString*)stringValue; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITBlob.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITBlob.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITBlob.h" 10 | #import "GITRepo.h" 11 | #import "GITErrors.h" 12 | 13 | #import "NSData+Searching.h" 14 | 15 | NSString * const kGITObjectBlobName = @"blob"; 16 | 17 | /*! \cond 18 | Make properties readwrite so we can use 19 | them within the class. 20 | */ 21 | @interface GITBlob () 22 | @property(readwrite,copy) NSData * data; 23 | @end 24 | /*! \endcond */ 25 | 26 | @implementation GITBlob 27 | @synthesize data; 28 | 29 | + (NSString*)typeName 30 | { 31 | return kGITObjectBlobName; 32 | } 33 | - (GITObjectType)objectType 34 | { 35 | return GITObjectTypeBlob; 36 | } 37 | 38 | #pragma mark - 39 | #pragma mark Deprecated Initialisers 40 | - (id)initWithSha1:(NSString*)newSha1 data:(NSData*)raw repo:(GITRepo*)theRepo 41 | { 42 | if (self = [super initType:kGITObjectBlobName sha1:newSha1 43 | size:[raw length] repo:theRepo]) 44 | { 45 | self.data = raw; 46 | } 47 | return self; 48 | } 49 | 50 | #pragma mark - 51 | #pragma mark Mem overrides 52 | - (void)dealloc 53 | { 54 | self.data = nil; 55 | [super dealloc]; 56 | } 57 | - (id)copyWithZone:(NSZone*)zone 58 | { 59 | GITBlob * blob = (GITBlob*)[super copyWithZone:zone]; 60 | blob.data = self.data; 61 | return blob; 62 | } 63 | 64 | #pragma mark - 65 | #pragma mark Data Parser 66 | - (BOOL)parseRawData:(NSData*)raw error:(NSError**)error 67 | { 68 | self.data = raw; 69 | return YES; 70 | } 71 | 72 | #pragma mark - 73 | #pragma mark Blob methods 74 | - (BOOL)canBeRepresentedAsString 75 | { 76 | // If we can't find a null byte then it can be represented as string 77 | if ([self.data rangeOfNullTerminatedBytesFrom:0].location == NSNotFound) 78 | return YES; 79 | return NO; 80 | } 81 | - (NSString*)stringValue 82 | { 83 | return [[[NSString alloc] initWithData:self.data encoding:NSASCIIStringEncoding] autorelease]; 84 | } 85 | 86 | #pragma mark - 87 | #pragma mark Output Methods 88 | - (NSData*)rawContent 89 | { 90 | return self.data; 91 | } 92 | @end -------------------------------------------------------------------------------- /CocoaGit/Core/GITCommit.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITCommit.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObject.h" 11 | 12 | extern NSString * const kGITObjectCommitName; 13 | 14 | @class GITTree, GITActor, GITDateTime; 15 | @interface GITCommit : GITObject 16 | { 17 | NSString * treeSha1; 18 | NSArray * parents; 19 | NSArray * parentShas; 20 | 21 | GITTree * tree; 22 | 23 | GITActor * author; 24 | GITActor * committer; 25 | 26 | GITDateTime * authored; 27 | GITDateTime * committed; 28 | unsigned long sortDate; 29 | 30 | NSString * message; 31 | NSData *cachedRawData; 32 | } 33 | 34 | @property(readonly,copy) NSString * treeSha1; 35 | @property(readonly,copy) NSString * parentSha1; 36 | @property(readwrite,retain) NSArray * parentShas; 37 | @property(readonly,copy) GITTree * tree; 38 | @property(readonly,copy) GITCommit * parent; 39 | @property(readonly,copy) NSArray *parents; 40 | @property(readonly,copy) GITActor * author; 41 | @property(readonly,copy) GITActor * committer; 42 | @property(readonly,copy) GITDateTime * authored; 43 | @property(readonly,copy) GITDateTime * committed; 44 | @property(readonly) unsigned long sortDate; 45 | @property(readonly,copy) NSString * message; 46 | 47 | - (BOOL)isFirstCommit; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITObject+Parsing.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITObject+Parsing.h 3 | // CocoaGit 4 | // 5 | // Created by Brian Chapados on 4/29/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObject.h" 11 | 12 | struct objectRecord { 13 | char *startPattern; 14 | NSUInteger patternLen; 15 | NSInteger startLen; 16 | NSUInteger matchLen; 17 | char endChar; 18 | }; 19 | 20 | @interface GITObject (Parsing) 21 | BOOL parseObjectRecord(const char **buffer, struct objectRecord delim, const char **matchStart, NSUInteger *matchLength); 22 | // 'create' prefix indicates that the caller owns the string 23 | - (NSString *) createStringWithObjectRecord:(struct objectRecord)record bytes:(const char **)bytes; 24 | - (NSString *) createStringWithObjectRecord:(struct objectRecord)record bytes:(const char **)bytes encoding:(NSStringEncoding)encoding; 25 | @end 26 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITObject+Parsing.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITObject+Parsing.m 3 | // CocoaGit 4 | // 5 | // Created by Brian R. Chapados on 4/29/09. 6 | // Copyright 2009 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "GITObject+Parsing.h" 10 | 11 | 12 | @implementation GITObject (Parsing) 13 | BOOL parseObjectRecord(const char **buffer, struct objectRecord record, const char **matchStart, NSUInteger *matchLength) 14 | { 15 | const char *buf = *buffer; 16 | if ( record.patternLen > 0 && memcmp(buf, record.startPattern, record.patternLen) ) { 17 | //NSLog(@"start pattern does not match: %s\nbuf:%s", record.startPattern, buf); 18 | return NO; 19 | } 20 | 21 | // set start position 22 | const char *start; 23 | if ( record.startLen > 0 ) { 24 | start = buf+record.startLen; 25 | } else { 26 | start = buf+record.patternLen; 27 | } 28 | 29 | // set end position, and reset startLen if its relative to the end (startLen < 0) 30 | const char *end = start; 31 | if ( (record.startLen >= 0) && (record.matchLen > 0) ) { 32 | end = start+record.matchLen; 33 | } else { 34 | while ( *end++ != record.endChar ) 35 | ; 36 | // TODO: BRC- use size for bounds check 37 | if ( record.startLen < 0 ) { 38 | // move the start pointer 39 | NSUInteger len = end - start; 40 | start += len + record.startLen; 41 | } 42 | --end; // end should point to the delimiting char 43 | } 44 | 45 | // check that end = endChar, otherwise there was a parsing problem 46 | if ( end[0] != record.endChar ) { 47 | NSLog(@"end delimiter (%c) does not match end char:%c\n", record.endChar, end[0]); 48 | return NO; 49 | } 50 | 51 | // set matchLen 52 | NSUInteger matchLen = record.matchLen; 53 | if ( record.matchLen == 0 ) 54 | matchLen = end - start; 55 | 56 | if ( matchStart != NULL ) 57 | *matchStart = start; 58 | if ( matchLength != NULL ) 59 | *matchLength = matchLen; 60 | 61 | *buffer = end + 1; // skip over the delimiting char 62 | return YES; 63 | } 64 | 65 | // 'create' prefix indicates that the caller owns the string 66 | - (NSString *) createStringWithObjectRecord:(struct objectRecord)record bytes:(const char **)bytes 67 | { 68 | return [self createStringWithObjectRecord:record bytes:bytes encoding:NSASCIIStringEncoding]; 69 | } 70 | 71 | // 'create' prefix indicates that the caller owns the string 72 | - (NSString *) createStringWithObjectRecord:(struct objectRecord)record bytes:(const char **)bytes encoding:(NSStringEncoding)stringEncoding 73 | { 74 | const char *start; 75 | NSUInteger len; 76 | if ( !parseObjectRecord(bytes, record, &start, &len) ) 77 | return nil; 78 | return [[NSString alloc] initWithBytes:start 79 | length:len 80 | encoding:stringEncoding]; 81 | } 82 | @end 83 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITTag.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITTag.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObject.h" 11 | 12 | extern NSString * const kGITObjectTagName; 13 | 14 | @class GITCommit, GITActor, GITDateTime; 15 | @interface GITTag : GITObject 16 | { 17 | NSString * name; 18 | NSString * objectSha1; 19 | 20 | // At such time as Tags can reference objects 21 | // other than commits we'll change this. 22 | GITCommit * commit; 23 | GITActor * tagger; 24 | 25 | GITDateTime * tagged; 26 | 27 | NSString * message; 28 | } 29 | 30 | @property(readonly,copy) NSString * name; 31 | @property(readonly,copy) NSString * objectSha1; 32 | @property(readonly,copy) GITCommit * commit; 33 | @property(readonly,copy) GITActor * tagger; 34 | @property(readonly,copy) GITDateTime * tagged; 35 | @property(readonly,copy) NSString * message; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITTree.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITTree.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObject.h" 11 | #import "GITTreeEntry.h" 12 | 13 | extern NSString * const kGITObjectTreeName; 14 | 15 | /*! Git object type representing a directory. 16 | */ 17 | @interface GITTree : GITObject 18 | { 19 | NSArray * entries; //!< Array of entrys in this tree. 20 | } 21 | 22 | @property(readonly,copy) NSArray * entries; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITTree.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITTree.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITTree.h" 10 | #import "GITRepo.h" 11 | #import "GITTreeEntry.h" 12 | #import "GITErrors.h" 13 | 14 | NSString * const kGITObjectTreeName = @"tree"; 15 | 16 | /*! \cond 17 | Make properties readwrite so we can use 18 | them within the class. 19 | */ 20 | @interface GITTree () 21 | @property(readwrite,copy) NSArray * entries; 22 | @end 23 | /*! \endcond */ 24 | 25 | @implementation GITTree 26 | @synthesize entries; 27 | 28 | + (NSString*)typeName 29 | { 30 | return kGITObjectTreeName; 31 | } 32 | - (GITObjectType)objectType 33 | { 34 | return GITObjectTypeTree; 35 | } 36 | 37 | #pragma mark - 38 | #pragma mark Mem overrides 39 | - (void)dealloc 40 | { 41 | self.entries = nil; 42 | [super dealloc]; 43 | } 44 | - (id)copyWithZone:(NSZone*)zone 45 | { 46 | GITTree * tree = (GITTree*)[super copyWithZone:zone]; 47 | tree.entries = self.entries; 48 | 49 | return tree; 50 | } 51 | 52 | #pragma mark - 53 | #pragma mark Data Parser 54 | - (BOOL)parseRawData:(NSData*)raw error:(NSError**)error 55 | { 56 | // TODO: Update this method to support errors 57 | NSError * undError; 58 | NSString * errorDescription; 59 | 60 | NSString * dataStr = [[NSString alloc] initWithData:raw 61 | encoding:NSASCIIStringEncoding]; 62 | 63 | NSMutableArray *treeEntries = [NSMutableArray arrayWithCapacity:2]; 64 | unsigned entryStart = 0; 65 | 66 | do { 67 | NSRange searchRange = NSMakeRange(entryStart, [dataStr length] - entryStart); 68 | NSUInteger entrySha1Start = [dataStr rangeOfString:@"\0" 69 | options:0 70 | range:searchRange].location; 71 | 72 | NSRange entryRange = NSMakeRange(entryStart, 73 | entrySha1Start - entryStart + kGITPackedSha1Length + 1); 74 | 75 | NSString * treeLine = [dataStr substringWithRange:entryRange]; 76 | GITTreeEntry * entry = [[GITTreeEntry alloc] initWithRawString:treeLine parent:self error:&undError]; 77 | 78 | if (!entry) 79 | { 80 | errorDescription = NSLocalizedString(@"Failed to parse entry for tree", @"GITErrorObjectParsingFailed (GITTree)"); 81 | GITErrorWithInfo(error, GITErrorObjectParsingFailed, NSLocalizedDescriptionKey, errorDescription, NSUnderlyingErrorKey, undError, nil); 82 | return NO; 83 | } 84 | 85 | [treeEntries addObject:entry]; 86 | [entry release]; 87 | entryStart = entryRange.location + entryRange.length; 88 | } while(entryStart < [dataStr length]); 89 | 90 | self.entries = treeEntries; 91 | [dataStr release]; 92 | 93 | return YES; 94 | } 95 | 96 | #pragma mark - 97 | #pragma mark Output Methods 98 | - (NSData*)rawContent 99 | { 100 | NSMutableData * content = [NSMutableData dataWithCapacity:self.size]; 101 | for (GITTreeEntry * entry in self.entries) 102 | { 103 | [content appendData:[entry raw]]; 104 | } 105 | return [content copy]; 106 | } 107 | 108 | @end 109 | -------------------------------------------------------------------------------- /CocoaGit/Core/GITTreeEntry.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITTreeEntry.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern const NSUInteger kGITPackedSha1Length; 12 | extern const NSUInteger kGITUnpackedSha1Length; 13 | 14 | @class GITObject, GITTree; 15 | /*! An entry in tree listing. 16 | * \todo Consider changing from having a GITRepo instance 17 | * as part of the class to having an instance of the tree 18 | * which the entry is a part of. We can then defer to the 19 | * trees repo for object loading. We then need to be very 20 | * careful about creating memory dependencies which are 21 | * difficult to manage and may result in memory leakage. 22 | */ 23 | @interface GITTreeEntry : NSObject 24 | { 25 | NSString * name; //!< Name of the entry, either a file or directory name 26 | NSUInteger mode; //!< File mode of the entry 27 | NSString * sha1; //!< SHA1 of the object referenced 28 | GITTree * parent; //!< The tree object this entry belongs to. 29 | GITObject * object; //!< The object which is referenced. This is lazy loaded. 30 | } 31 | 32 | @property(readonly,copy) NSString * name; 33 | @property(readonly,assign) NSUInteger mode; 34 | @property(readonly,copy) NSString * sha1; 35 | @property(readonly,copy) GITTree * parent; 36 | @property(readonly,copy) GITObject * object; 37 | 38 | #pragma mark - 39 | #pragma mark Deprecated Initialisers 40 | /*! Creates and returns a new entry by extracting the information tree line. 41 | * \param line The raw line as extracted from a tree object file 42 | * \param parent The parent tree this entry belongs to 43 | * \return A new entry 44 | * \deprecated Use -initWithRawString:parent:error: instead 45 | */ 46 | - (id)initWithTreeLine:(NSString*)line parent:(GITTree*)parent; 47 | 48 | /*! Creates and returns a new entry the given settings 49 | * \param mode The file mode of the file or directory described 50 | * \param name The file name of the filr or directory described 51 | * \param hash The SHA1 of the object referenced 52 | * \param parent The parent tree this entry belongs to 53 | * \return A new entry 54 | * \deprecated Use -initWithFileMode:name:sha1:parent:error: instead 55 | */ 56 | - (id)initWithMode:(NSUInteger)mode name:(NSString*)name 57 | sha1:(NSString*)hash parent:(GITTree*)parent; 58 | 59 | /*! Creates and returns a new entry the given settings 60 | * \param mode The file mode as a string of the file or directory described 61 | * \param name The file name of the filr or directory described 62 | * \param hash The SHA1 of the object referenced 63 | * \param parent The parent tree this entry belongs to 64 | * \return A new entry 65 | * \deprecated Use -initWithFileMode:name:sha1:parent:error: instead 66 | */ 67 | - (id)initWithModeString:(NSString*)mode name:(NSString*)name 68 | sha1:(NSString*)hash parent:(GITTree*)parent; 69 | 70 | #pragma mark - 71 | #pragma mark Error Aware Initialisers 72 | /*! Creates and returns a new entry by extracting the fields from the raw string. 73 | * \param raw The raw string from a tree object file 74 | * \param parent The parent tree this entry belongs to 75 | * \param[out] error Error containing a description of any errors if they occurred 76 | * \return A new entry or nil if an error occurred 77 | * \par Errors: 78 | * \li \c GITErrorObjectParsingFailed indicates a problem parsing the formatted tree entry 79 | */ 80 | - (id)initWithRawString:(NSString*)raw parent:(GITTree*)parent error:(NSError**)error; 81 | 82 | /*! Creates and returns a new entry the given settings 83 | * \param mode The file mode of the file or directory described 84 | * \param name The file name of the filr or directory described 85 | * \param sha1 The SHA1 of the object referenced 86 | * \param parent The parent tree this entry belongs to 87 | * \param[out] error Error containing a description of any errors if they occurred 88 | * \return A new entry or nil if error 89 | */ 90 | - (id)initWithFileMode:(NSUInteger)mode name:(NSString*)name sha1:(NSString*)sha1 parent:(GITTree*)parent error:(NSError**)error; 91 | 92 | - (NSData*)raw; 93 | @end 94 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITActor.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITUser.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 01/07/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /*! A git user. 12 | * The actor class encapsulates the name and email pair for a user 13 | * of git. The actor can be thought of as similar to the 14 | * \code 15 | * git config user.name 16 | * git config user.email\endcode 17 | * configuration settings. 18 | * 19 | * \see GITCommit 20 | * \see GITTag 21 | * \internal 22 | * Presently only used by Tag and Commit objects. 23 | */ 24 | @interface GITActor : NSObject { 25 | NSString * name; //!< Name of the actor 26 | NSString * email; //!< Email address of the actor 27 | } 28 | 29 | @property(readonly,copy) NSString * name; 30 | @property(readonly,copy) NSString * email; 31 | 32 | + (id) actorWithName:(NSString *)theName; 33 | + (id) actorWithName:(NSString *)theName email:(NSString *)theEmail; 34 | + (id) actorWithString:(NSString *)raw; 35 | 36 | /*! Creates and returns an actor object with the provided name. 37 | * The created actor object will have an email address of nil. 38 | * \param theName The name of the actor to create. 39 | * \return An actor object with the provided name. 40 | */ 41 | - (id)initWithName:(NSString*)theName; 42 | 43 | /*! Creates and returns an actor object with the provided name and email. 44 | * \param theName The name of the actor. 45 | * \param theEmail The email address of the actor. 46 | * \return An actor object with the provided name and email. 47 | */ 48 | - (id)initWithName:(NSString*)theName email:(NSString*)theEmail; 49 | 50 | /*! Creates and returns an actor object by parsing the name and email from 51 | * a string contained in a GITCommit header (author or committer) line. 52 | * This method expects pre-processed input of the form: "[name] <[email]". 53 | * example: "E. L. Gato ", 82 | self.name, self.email]; 83 | else 84 | return self.name; 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITDateTime.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITDateTime.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 07/10/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface GITDateTime : NSObject { 13 | NSDate * date; 14 | NSTimeZone * timezone; 15 | } 16 | 17 | @property(readonly,copy) NSDate * date; 18 | @property(readonly,copy) NSTimeZone * timezone; 19 | 20 | - (id)initWithDate:(NSDate*)theDate timeZone:(NSTimeZone*)theTimeZone; 21 | - (id)initWithTimestamp:(NSTimeInterval)seconds timeZoneOffset:(NSString*)offset; 22 | 23 | /*! Creates and returns dateTime object given the BSD time (time in seconds since 1970) 24 | * and the timeZone offset from GMT in units of hours*100. The units of hours*100, 25 | * though bizarre, result from converting a typical timeZone string "-0700" into an 26 | * integer. 27 | * \param seconds BSD time (in seconds since 1970). 28 | * \param tz timeZone offset from GMT in units of hours*100. 29 | * \return An actor object with the extracted name and email. 30 | */ 31 | - (id) initWithBSDTime:(unsigned long)seconds timeZoneOffset:(NSInteger)tz; 32 | - (NSComparisonResult)compare:(GITDateTime*)object; 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITDateTime.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITDateTime.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 07/10/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITDateTime.h" 10 | #import "NSTimeZone+Offset.h" 11 | 12 | /*! \cond 13 | Make properties readwrite so we can use 14 | them within the class. 15 | */ 16 | @interface GITDateTime () 17 | @property(readwrite,copy) NSDate * date; 18 | @property(readwrite,copy) NSTimeZone * timezone; 19 | @end 20 | /*! \endcond */ 21 | 22 | @implementation GITDateTime 23 | @synthesize date; 24 | @synthesize timezone; 25 | 26 | - (id)initWithDate:(NSDate*)theDate timeZone:(NSTimeZone*)theTimeZone 27 | { 28 | if (self = [super init]) 29 | { 30 | self.date = theDate; 31 | self.timezone = theTimeZone; 32 | } 33 | return self; 34 | } 35 | - (id)initWithTimestamp:(NSTimeInterval)seconds timeZoneOffset:(NSString*)offset 36 | { 37 | return [self initWithDate:[NSDate dateWithTimeIntervalSince1970:seconds] 38 | timeZone:[NSTimeZone timeZoneWithStringOffset:offset]]; 39 | } 40 | 41 | - (id) initWithBSDTime:(unsigned long)timeInSec timeZoneOffset:(NSInteger)tz 42 | { 43 | NSDate *aDate = [NSDate dateWithTimeIntervalSince1970:(NSTimeInterval)timeInSec]; 44 | NSInteger min = abs(tz); 45 | min = ((min/100)*60) + (min % 100); 46 | min = (tz < 0) ? -min : min; 47 | NSTimeZone *aTimeZone = [NSTimeZone timeZoneForSecondsFromGMT:(min*60)]; 48 | return [self initWithDate:aDate timeZone:aTimeZone]; 49 | } 50 | 51 | - (void)dealloc 52 | { 53 | self.date = nil; 54 | self.timezone = nil; 55 | [super dealloc]; 56 | } 57 | - (id)copyWithZone:(NSZone*)zone 58 | { 59 | return [[GITDateTime allocWithZone:zone] initWithDate:self.date timeZone:self.timezone]; 60 | } 61 | - (NSString*)description 62 | { 63 | return [NSString stringWithFormat:@"%.0f %@", 64 | [self.date timeIntervalSince1970], [self.timezone offsetString]]; 65 | } 66 | - (NSComparisonResult)compare:(GITDateTime*)anotherGITDateTime 67 | { 68 | NSParameterAssert(anotherGITDateTime); 69 | 70 | NSCalendar *selfDateCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 71 | [selfDateCalendar setTimeZone:timezone]; 72 | NSCalendar *anotherDateCalendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease]; 73 | [anotherDateCalendar setTimeZone:anotherGITDateTime.timezone]; 74 | 75 | NSCalendarUnit unitFlags = NSYearCalendarUnit|NSMonthCalendarUnit|NSDayCalendarUnit|kCFCalendarUnitHour|kCFCalendarUnitMinute|kCFCalendarUnitSecond; 76 | 77 | NSDateComponents *selfDateComponents = [selfDateCalendar components:unitFlags fromDate:date]; 78 | NSDateComponents *anotherDateComponents = [anotherDateCalendar components:unitFlags fromDate:anotherGITDateTime.date]; 79 | 80 | NSDate *selfDate = [selfDateCalendar dateFromComponents:selfDateComponents]; 81 | NSDate *anotherDate = [anotherDateCalendar dateFromComponents:anotherDateComponents]; 82 | 83 | return [selfDate compare:anotherDate]; 84 | } 85 | @end 86 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITErrors.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITError.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 09/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | // We use the __git_error and __git_error_domain macros to 9 | // make it easier to enter and update the error codes in 10 | // the project. If you define them here with the macro then 11 | // you can copy/paste the same code into GITErrors.m and 12 | // then add the value argument to the end of them. 13 | // 14 | 15 | #import 16 | #define __git_error(code) extern const NSInteger code 17 | #define __git_error_domain(dom) extern NSString * dom 18 | 19 | __git_error_domain(GITErrorDomain); 20 | 21 | #import "NSError-OBExtensions.h" 22 | 23 | // Define GITError* macros to use the OmniBase _OBError helper functions. If we decide to move away from OmniBase code, we can just redfine these. 24 | #define GITError(error, code, description) _OBError(error, GITErrorDomain, code, __FILE__, __LINE__, NSLocalizedDescriptionKey, description, nil) 25 | #define GITErrorWithInfo(error, code, ...) _OBError(error, GITErrorDomain, code, __FILE__, __LINE__, ## __VA_ARGS__) 26 | 27 | #pragma mark Object Loading Errors 28 | __git_error(GITErrorObjectSizeMismatch); 29 | __git_error(GITErrorObjectNotFound); 30 | __git_error(GITErrorObjectTypeMismatch); 31 | __git_error(GITErrorObjectParsingFailed); 32 | 33 | #pragma mark File Reading Errors 34 | __git_error(GITErrorFileNotFound); 35 | 36 | #pragma mark Store Error Codes 37 | __git_error(GITErrorObjectStoreNotAccessible); 38 | __git_error(GITErrorRefStoreNotAccessible); 39 | 40 | #pragma mark PACK and Index Error Codes 41 | __git_error(GITErrorPackIndexUnsupportedVersion); 42 | __git_error(GITErrorPackIndexCorrupted); 43 | __git_error(GITErrorPackIndexChecksumMismatch); 44 | __git_error(GITErrorPackIndexNotAvailable); 45 | __git_error(GITErrorPackFileInvalid); 46 | __git_error(GITErrorPackFileNotSupported); 47 | __git_error(GITErrorPackFileChecksumMismatch); 48 | 49 | #undef __git_error 50 | #undef __git_error_domain 51 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITErrors.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITError.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 09/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITErrors.h" 10 | #define __git_error(code, val) const NSInteger code = val 11 | #define __git_error_domain(dom, str) NSString * dom = str 12 | 13 | __git_error_domain(GITErrorDomain, @"com.manicpanda.GIT.ErrorDomain"); 14 | 15 | #pragma mark Object Loading Errors 16 | __git_error(GITErrorObjectSizeMismatch, -1); 17 | __git_error(GITErrorObjectNotFound, -2); 18 | __git_error(GITErrorObjectTypeMismatch, -3); 19 | __git_error(GITErrorObjectParsingFailed, -4); 20 | 21 | #pragma mark File Reading Errors 22 | __git_error(GITErrorFileNotFound, -100); 23 | 24 | #pragma mark Store Error Codes 25 | __git_error(GITErrorObjectStoreNotAccessible, -200); 26 | __git_error(GITErrorRefStoreNotAccessible, -201); 27 | 28 | #pragma mark PACK and Index Error Codes 29 | __git_error(GITErrorPackIndexUnsupportedVersion, -300); 30 | __git_error(GITErrorPackIndexCorrupted, -301); 31 | __git_error(GITErrorPackIndexChecksumMismatch, -302); 32 | __git_error(GITErrorPackIndexNotAvailable, -303); 33 | 34 | __git_error(GITErrorPackFileInvalid, -400); 35 | __git_error(GITErrorPackFileNotSupported, -401); 36 | __git_error(GITErrorPackFileChecksumMismatch, -402); 37 | 38 | #undef __git_error 39 | -------------------------------------------------------------------------------- /CocoaGit/Extra/GITUtilityBelt.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITUtilityBelt.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 12/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NSData * packSHA1FromBytes(const char *hexBytes); 12 | NSData * packSHA1(NSString * unpackedSHA1); 13 | NSString * unpackSHA1FromString(NSString * packedSHA1); 14 | NSString * unpackSHA1FromData(NSData * packedSHA1); 15 | NSString * unpackSHA1FromBytes(const uint8_t * bytes, unsigned int length); 16 | BOOL isSha1StringValid(NSString *shaString); 17 | NSData * bytesToData(const uint8_t *bytes, unsigned int length); 18 | NSUInteger integerFromBytes(uint8_t * bytes, NSUInteger length); 19 | NSData * intToHexLength(NSUInteger length); 20 | NSUInteger hexLengthToInt(NSData *lengthData); -------------------------------------------------------------------------------- /CocoaGit/Git.h: -------------------------------------------------------------------------------- 1 | // 2 | // GIT.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/01/2009. 6 | // Copyright 2009 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Main source files are in the Sources directory 12 | #import "GITErrors.h" 13 | 14 | #pragma mark Repo and object access 15 | #import "GITRepo.h" 16 | #pragma mark GIT Objects 17 | #import "GITObject.h" 18 | #import "GITCommit.h" 19 | #import "GITBlob.h" 20 | #import "GITTree.h" 21 | #import "GITTag.h" 22 | #pragma mark GIT Helper objects 23 | #import "GITTreeEntry.h" 24 | #import "GITDateTime.h" 25 | #import "GITActor.h" 26 | -------------------------------------------------------------------------------- /CocoaGit/Graph/GITCommitEnumerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITCommitEnumerator.h 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/24/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef enum { 12 | GITEnumeratorDFS = 0, 13 | GITEnumeratorBFS = 1, 14 | } GITEnumeratorTraversalMode; 15 | 16 | @class GITRepo, GITCommit; 17 | @interface GITCommitEnumerator : NSEnumerator { 18 | GITRepo *repo; 19 | GITEnumeratorTraversalMode mode; 20 | 21 | NSMutableArray *nodeQueue; 22 | NSMutableSet *visitedNodes; 23 | BOOL started; 24 | } 25 | @property (nonatomic, readwrite, retain) GITRepo *repo; 26 | + (id) enumeratorWithRepo:(GITRepo *)gitRepo; 27 | + (id) enumeratorWithRepo:(GITRepo *)gitRepo mode:(GITEnumeratorTraversalMode)theMode; 28 | - (void) setStartCommit:(GITCommit *)startCommit; 29 | @end 30 | -------------------------------------------------------------------------------- /CocoaGit/Graph/GITCommitEnumerator.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITCommitEnumerator.m 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/24/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import "GITCommitEnumerator.h" 10 | #import "GITCommit.h" 11 | #import "GITRepo.h" 12 | 13 | @interface GITCommitEnumerator() 14 | - (id) initWithRepo:(GITRepo *)gitRepo mode:(GITEnumeratorTraversalMode)theMode; 15 | @end 16 | 17 | @implementation GITCommitEnumerator 18 | @synthesize repo; 19 | 20 | + (id) enumeratorWithRepo:(GITRepo *)gitRepo 21 | { 22 | return [[[self alloc] initWithRepo:gitRepo mode:GITEnumeratorDFS] autorelease]; 23 | } 24 | 25 | + (id) enumeratorWithRepo:(GITRepo *)gitRepo mode:(GITEnumeratorTraversalMode)theMode; 26 | { 27 | return [[[self alloc] initWithRepo:gitRepo mode:theMode] autorelease]; 28 | } 29 | 30 | - (id) init 31 | { 32 | if ( !(self = [super init]) ) { 33 | [self release]; 34 | return nil; 35 | } 36 | nodeQueue = [NSMutableArray new]; 37 | visitedNodes = [NSMutableSet new]; 38 | mode = GITEnumeratorDFS; 39 | started = NO; 40 | return self; 41 | } 42 | 43 | - (id) initWithRepo:(GITRepo *)gitRepo mode:(GITEnumeratorTraversalMode)theMode 44 | { 45 | if ( ![self init] ) { 46 | return nil; 47 | } 48 | [self setRepo:gitRepo]; 49 | [self setStartCommit:[gitRepo head]]; 50 | mode = theMode; 51 | return self; 52 | } 53 | 54 | - (void) dealloc 55 | { 56 | [repo release], repo = nil; 57 | [nodeQueue release], nodeQueue = nil; 58 | [visitedNodes release], visitedNodes = nil; 59 | [super dealloc]; 60 | } 61 | 62 | - (void) setStartCommit:(GITCommit *)startCommit; 63 | { 64 | NSAssert(!started, @"Cannot set start commit after enumeration has started"); 65 | if ( !started ) 66 | [nodeQueue addObject:startCommit]; 67 | } 68 | 69 | // traverse through the graph of commits, in the order specified by 'mode' 70 | // returning each commit object to the caller 71 | - (id) nextObject 72 | { 73 | if ( started ) { 74 | if ( nodeQueue == nil || [nodeQueue count] == 0 ) { 75 | [visitedNodes release], visitedNodes = nil; 76 | [nodeQueue release], nodeQueue = nil; 77 | return nil; 78 | } 79 | } else { 80 | if ( nodeQueue == nil || [nodeQueue count] == 0 ) { 81 | [self setStartCommit:[repo head]]; 82 | } 83 | started = YES; 84 | } 85 | 86 | GITCommit *currentCommit; 87 | if ( mode == GITEnumeratorDFS ) { 88 | // DFS => LIFO queue 89 | currentCommit = (GITCommit *)[[nodeQueue lastObject] retain]; 90 | [nodeQueue removeLastObject]; 91 | } else { 92 | // BFS => FIFO queue 93 | currentCommit = (GITCommit *)[[nodeQueue objectAtIndex:0] retain]; 94 | [nodeQueue removeObjectAtIndex:0]; 95 | } 96 | 97 | id key = [currentCommit sha1]; 98 | if ( ![visitedNodes containsObject:key] ) { 99 | [visitedNodes addObject:key]; 100 | } 101 | 102 | for ( NSString *parentSha1 in [currentCommit parentShas] ) { 103 | if ( ![visitedNodes containsObject:parentSha1] ) { 104 | GITCommit *c = [[self repo] commitWithSha1:parentSha1]; 105 | [visitedNodes addObject:parentSha1]; 106 | [nodeQueue addObject:c]; 107 | } 108 | } 109 | return [currentCommit autorelease]; 110 | } 111 | 112 | - (NSArray *) allObjects 113 | { 114 | NSMutableArray *all = [NSMutableArray array]; 115 | id commit; 116 | while ( commit = [self nextObject] ) { 117 | [all addObject:commit]; 118 | } 119 | return [NSArray arrayWithArray:all]; 120 | } 121 | 122 | @end -------------------------------------------------------------------------------- /CocoaGit/Graph/GITGraph.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITGraph.h 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/23/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class GITNode; 12 | @class GITCommit; 13 | @interface GITGraph : NSObject { 14 | NSMutableDictionary *nodes; 15 | } 16 | - (NSUInteger) countOfNodes; 17 | //- (NSUInteger) countOfEdges; 18 | 19 | - (BOOL) hasNode:(GITNode *)aNode; 20 | - (GITNode *) nodeWithKey:(NSString *)aKey; 21 | 22 | - (void) addNode:(GITNode *)newNode; 23 | - (void) removeNode:(GITNode *)aNode; 24 | - (void) addEdgeFromNode:(GITNode *)sourceNode toNode:(GITNode *)targetNode; 25 | //- (void) removeEdgeFromNode:(GITNode *)sourceNode toNode:(GITNode *)targetNode; 26 | 27 | - (void) buildGraphWithStartingCommit:(GITCommit *)commit; 28 | - (NSArray *) nodesSortedByDate; 29 | - (NSArray *) nodesSortedByTopology:(BOOL)useLifo; 30 | 31 | - (void) removeObjectsFromNodes; 32 | //- (void) addCommit:(GITCommit *)gitCommit; 33 | //- (void) removeCommit:(GITCommit *)gitCommit; 34 | //- (void) addCommit:(GITCommit *)gitCommit includeTree:(BOOL)includeTree; 35 | //- (void) removeCommit:(GITCommit *)gitCommit includeTree:(BOOL)includeTree; 36 | @end -------------------------------------------------------------------------------- /CocoaGit/Graph/GITNode.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITNode.h 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/23/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GITNode : NSObject 12 | { 13 | id key; 14 | id object; 15 | 16 | // These arrays DO NOT retain members 17 | CFMutableArrayRef inNodes; 18 | CFMutableArrayRef outNodes; 19 | 20 | @public 21 | BOOL visited; 22 | BOOL processed; 23 | NSUInteger indegree; 24 | unsigned long date; 25 | } 26 | @property (readwrite, copy) id key; 27 | @property (readwrite, retain) id object; 28 | @property (readwrite, assign) NSUInteger indegree; 29 | @property (readonly) unsigned long date; 30 | + (id) nodeWithObject:(id)anObject; 31 | - (id) initWithObject:(id)anObject; 32 | - (void) resetIndegree; 33 | - (void) incrementIndegree; 34 | - (void) decrementIndegree; 35 | 36 | - (NSArray *) outNodes; 37 | - (void) addOutNode:(id)outNode; 38 | - (void) removeOutNode:(id)outNode; 39 | 40 | - (NSArray *) inNodes; 41 | - (void) addInNode:(id)inNode; 42 | - (void) removeInNode:(id)inNode; 43 | 44 | - (BOOL) wasVisited; 45 | - (void) visit; 46 | - (void) unvisit; 47 | - (void) incrementIndegree; 48 | - (void) decrementIndegree; 49 | 50 | - (void) removeObject; 51 | @end -------------------------------------------------------------------------------- /CocoaGit/Graph/GITNode.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITNode.m 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/23/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import "GITNode.h" 10 | #import "GITCommit.h" 11 | 12 | @implementation GITNode 13 | @synthesize key, object; 14 | @synthesize indegree, date; 15 | 16 | static Boolean GITNodeEqual(const void *a, const void *b) 17 | { 18 | const GITNode *u = a; 19 | const GITNode *v = b; 20 | return (Boolean)([u isEqual:v]); 21 | } 22 | 23 | static CFArrayCallBacks kGITNodeArrayCallbacks = {0, NULL, NULL, NULL, GITNodeEqual}; 24 | 25 | + (id) nodeWithObject:(id)anObject; 26 | { 27 | return [[[self alloc] initWithObject:anObject] autorelease]; 28 | } 29 | 30 | - (id) initWithObject:(id)anObject; 31 | { 32 | if ( !(self = [super init]) ) { 33 | [self release]; 34 | return nil; 35 | } 36 | if ( !anObject ) { 37 | // isEqual and hash depend on object, so it can't be nil 38 | [self release]; 39 | return nil; 40 | } 41 | [self setKey:[(GITObject *)anObject sha1]]; 42 | [self setObject:anObject]; 43 | date = [anObject sortDate]; 44 | inNodes = CFArrayCreateMutable(NULL, 0, &kGITNodeArrayCallbacks); 45 | outNodes = CFArrayCreateMutable(NULL, 0, &kGITNodeArrayCallbacks); 46 | 47 | return self; 48 | } 49 | 50 | - (void) dealloc 51 | { 52 | CFRelease(inNodes); 53 | CFRelease(outNodes); 54 | [key release], key = nil; 55 | if (object) 56 | [object release], object = nil; 57 | [super dealloc]; 58 | } 59 | 60 | - (BOOL) isEqual:(id)other 61 | { 62 | if ( self == other ) 63 | return YES; 64 | return [[self key] isEqual:[other key]]; 65 | } 66 | 67 | - (NSUInteger) hash 68 | { 69 | return [key hash]; 70 | } 71 | 72 | - (BOOL) wasVisited { return visited; } 73 | 74 | - (void) visit { visited = YES; } 75 | 76 | - (void) unvisit { visited = NO; } 77 | 78 | - (void) resetIndegree 79 | { 80 | indegree = CFArrayGetCount(inNodes); 81 | } 82 | 83 | - (void) incrementIndegree { indegree++; } 84 | 85 | - (void) decrementIndegree { indegree--; } 86 | 87 | - (NSArray *) inNodes 88 | { 89 | return [NSArray arrayWithArray:(NSMutableArray *)inNodes]; 90 | } 91 | 92 | - (void) addInNode:(id)inNode; 93 | { 94 | CFArrayAppendValue(inNodes, inNode); 95 | } 96 | 97 | - (void) removeInNode:(id)inNode; 98 | { 99 | NSUInteger i = CFArrayGetFirstIndexOfValue(inNodes, 100 | CFRangeMake(0, CFArrayGetCount(inNodes)), 101 | inNode); 102 | CFArrayRemoveValueAtIndex(inNodes, i); 103 | } 104 | 105 | - (NSArray *) outNodes 106 | { 107 | return [NSArray arrayWithArray:(NSMutableArray *)outNodes]; 108 | } 109 | 110 | - (void) addOutNode:(id)outNode; 111 | { 112 | CFArrayAppendValue(outNodes, outNode); 113 | } 114 | 115 | - (void) removeOutNode:(id)outNode; 116 | { 117 | NSUInteger i = CFArrayGetFirstIndexOfValue(outNodes, 118 | CFRangeMake(0, CFArrayGetCount(outNodes)), 119 | outNode); 120 | CFArrayRemoveValueAtIndex(outNodes, i); 121 | } 122 | 123 | - (void) removeObject 124 | { 125 | [object release], object = nil; 126 | } 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /CocoaGit/Graph/GITRepo+Enumerators.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITRepo+Enumerators.h 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/30/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITRepo.h" 11 | 12 | @class GITCommitEnumerator; 13 | @interface GITRepo (Enumerators) 14 | - (NSEnumerator *)commitEnumeratorBFS; 15 | - (NSEnumerator *)commitEnumeratorDFS; 16 | @end 17 | -------------------------------------------------------------------------------- /CocoaGit/Graph/GITRepo+Enumerators.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITRepo+Enumerators.m 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/30/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import "GITRepo+Enumerators.h" 10 | #import "GITCommitEnumerator.h" 11 | 12 | @implementation GITRepo (Enumerators) 13 | - (NSEnumerator *)commitEnumeratorBFS 14 | { 15 | return [GITCommitEnumerator enumeratorWithRepo:self mode:GITEnumeratorBFS]; 16 | } 17 | 18 | - (NSEnumerator *)commitEnumeratorDFS 19 | { 20 | return [GITCommitEnumerator enumeratorWithRepo:self mode:GITEnumeratorDFS]; 21 | } 22 | @end 23 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackFile.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackFile.h" 10 | 11 | @implementation GITPackFile 12 | #pragma mark - 13 | #pragma mark Class Cluster Alloc Methods 14 | + (id)alloc 15 | { 16 | if ([self isEqual:[GITPackFile class]]) 17 | return [GITPlaceholderPackFile alloc]; 18 | else return [super alloc]; 19 | } 20 | + (id)allocWithZone:(NSZone*)zone 21 | { 22 | if ([self isEqual:[GITPackFile class]]) 23 | return [GITPlaceholderPackFile allocWithZone:zone]; 24 | else return [super allocWithZone:zone]; 25 | } 26 | - (id)copyWithZone:(NSZone*)zone 27 | { 28 | return self; 29 | } 30 | 31 | #pragma mark - 32 | #pragma mark Primitive Methods 33 | - (NSUInteger)version 34 | { 35 | return 0; 36 | } 37 | - (GITPackIndex*)index 38 | { 39 | [self doesNotRecognizeSelector: _cmd]; 40 | return nil; 41 | } 42 | 43 | + (id)packFileWithPath:(NSString *)thePath 44 | { 45 | return [[[self alloc] initWithPath:thePath] autorelease]; 46 | } 47 | 48 | - (id)initWithPath:(NSString*)thePath 49 | { 50 | return [self initWithPath:thePath error:NULL]; 51 | } 52 | 53 | + (id)packFileWithPath:(NSString *)thePath error:(NSError **)error 54 | { 55 | return [[[self alloc] initWithPath:thePath error:error] autorelease]; 56 | } 57 | 58 | - (id)initWithPath:(NSString*)thePath error:(NSError **)error 59 | { 60 | [self doesNotRecognizeSelector: _cmd]; 61 | [self release]; 62 | return nil; 63 | } 64 | 65 | - (id)initWithPath:(NSString*)path indexPath:(NSString *)idxPath error:(NSError **)error 66 | { 67 | [self doesNotRecognizeSelector: _cmd]; 68 | [self release]; 69 | return nil; 70 | } 71 | 72 | - (id)initWithData:(NSData *)packData error:(NSError **)error 73 | { 74 | [self doesNotRecognizeSelector: _cmd]; 75 | [self release]; 76 | return nil; 77 | } 78 | 79 | - (NSData*)dataForObjectWithSha1:(NSString*)sha1 80 | { 81 | [self doesNotRecognizeSelector: _cmd]; 82 | return nil; 83 | } 84 | - (BOOL)loadObjectWithSha1:(NSString*)sha1 intoData:(NSData**)data 85 | type:(GITObjectType*)type error:(NSError**)error 86 | { 87 | [self doesNotRecognizeSelector: _cmd]; 88 | return NO; 89 | } 90 | 91 | #pragma mark - 92 | #pragma mark Checksum Methods 93 | - (NSData*)checksum 94 | { 95 | [self doesNotRecognizeSelector: _cmd]; 96 | return nil; 97 | } 98 | - (NSString*)checksumString 99 | { 100 | [self doesNotRecognizeSelector: _cmd]; 101 | return nil; 102 | } 103 | - (BOOL)verifyChecksum 104 | { 105 | [self doesNotRecognizeSelector: _cmd]; 106 | return NO; 107 | } 108 | 109 | #pragma mark - 110 | #pragma mark Derived Methods 111 | - (NSUInteger)numberOfObjects 112 | { 113 | return [[self index] numberOfObjects]; 114 | } 115 | - (BOOL)hasObjectWithSha1:(NSString*)sha1 116 | { 117 | return [[self index] hasObjectWithSha1:sha1]; 118 | } 119 | @end 120 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackFileVersion2.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackFileVersion2.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackFile.h" 10 | 11 | @class GITPackIndex; 12 | @interface GITPackFileVersion2 : GITPackFile 13 | { 14 | NSString * path; 15 | NSData * data; 16 | GITPackIndex * index; 17 | NSUInteger numberOfObjects; 18 | } 19 | 20 | // These may be removed at a later date. 21 | @property(readonly,copy) NSString * path; 22 | @property(readonly,retain) NSData * data; 23 | @property(readonly,retain) GITPackIndex * index; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackIndex.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackIndex.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackIndex.h" 10 | #import "GITUtilityBelt.h" 11 | 12 | @implementation GITPackIndex 13 | #pragma mark - 14 | #pragma mark Class Cluster Alloc Methods 15 | + (id)alloc 16 | { 17 | if ([self isEqual:[GITPackIndex class]]) 18 | return [GITPlaceholderPackIndex alloc]; 19 | else return [super alloc]; 20 | } 21 | + (id)allocWithZone:(NSZone*)zone 22 | { 23 | if ([self isEqual:[GITPackIndex class]]) 24 | return [GITPlaceholderPackIndex allocWithZone:zone]; 25 | else return [super allocWithZone:zone]; 26 | } 27 | - (id)copyWithZone:(NSZone*)zone 28 | { 29 | return self; 30 | } 31 | 32 | #pragma mark - 33 | #pragma mark Primitive Methods 34 | + (id)packIndexWithPath:(NSString*)thePath; 35 | { 36 | return [[[self alloc] initWithPath:thePath] autorelease]; 37 | } 38 | 39 | - (id)initWithPath:(NSString*)thePath 40 | { 41 | return [self initWithPath:thePath error:NULL]; 42 | } 43 | 44 | + (id)packIndexWithPath:(NSString*)thePath error:(NSError**)outError 45 | { 46 | return [[[self alloc] initWithPath:thePath error:outError] autorelease]; 47 | } 48 | 49 | - (id)initWithPath:(NSString*)thePath error:(NSError**)outError 50 | { 51 | [self doesNotRecognizeSelector: _cmd]; 52 | [self release]; 53 | return nil; 54 | } 55 | - (NSUInteger)version 56 | { 57 | return 0; 58 | } 59 | - (NSArray*)offsets 60 | { 61 | [self doesNotRecognizeSelector: _cmd]; 62 | return nil; 63 | } 64 | - (NSData*)checksum 65 | { 66 | [self doesNotRecognizeSelector: _cmd]; 67 | return nil; 68 | } 69 | - (NSData*)packChecksum 70 | { 71 | [self doesNotRecognizeSelector: _cmd]; 72 | return nil; 73 | } 74 | - (NSString*)checksumString 75 | { 76 | return unpackSHA1FromData([self checksum]); 77 | } 78 | - (NSString*)packChecksumString 79 | { 80 | return unpackSHA1FromData([self packChecksum]); 81 | } 82 | - (BOOL)verifyChecksum 83 | { 84 | [self doesNotRecognizeSelector: _cmd]; 85 | return NO; 86 | } 87 | - (off_t)packOffsetForSha1:(NSString *)sha1 88 | { 89 | return [self packOffsetForSha1:sha1 error:NULL]; 90 | } 91 | 92 | - (off_t)packOffsetForSha1:(NSString*)sha1 error:(NSError**)error; 93 | { 94 | [self doesNotRecognizeSelector: _cmd]; 95 | return 0; 96 | } 97 | 98 | - (off_t)baseOffsetWithOffset:(off_t)offset; 99 | { 100 | [self doesNotRecognizeSelector:_cmd]; 101 | return 0; 102 | } 103 | 104 | - (off_t)nextOffsetWithOffset:(off_t)offset; 105 | { 106 | [self doesNotRecognizeSelector: _cmd]; 107 | return 0; 108 | } 109 | - (off_t)packOffsetWithIndex:(NSUInteger)i; 110 | { 111 | [self doesNotRecognizeSelector: _cmd]; 112 | return 0; 113 | } 114 | - (NSString *)sha1WithOffset:(off_t)offset; 115 | { 116 | [self doesNotRecognizeSelector: _cmd]; 117 | return nil; 118 | } 119 | #pragma mark - 120 | #pragma mark Derived Methods 121 | - (NSUInteger)numberOfObjects 122 | { 123 | return [[[self offsets] lastObject] unsignedIntegerValue]; 124 | } 125 | - (NSUInteger)numberOfObjectsWithFirstByte:(uint8_t)byte 126 | { 127 | return [self rangeOfObjectsWithFirstByte:byte].length; 128 | } 129 | - (NSRange)rangeOfObjectsWithFirstByte:(uint8_t)byte 130 | { 131 | NSUInteger thisFanout, prevFanout = 0; 132 | thisFanout = [[[self offsets] objectAtIndex:byte] unsignedIntegerValue]; 133 | if (byte != 0x0) 134 | prevFanout = [[[self offsets] objectAtIndex:byte - 1] unsignedIntegerValue]; 135 | return NSMakeRange(prevFanout, thisFanout - prevFanout); 136 | } 137 | - (BOOL)hasObjectWithSha1:(NSString*)sha1 138 | { 139 | if ([self packOffsetForSha1:sha1] == NSNotFound) 140 | return NO; 141 | return YES; 142 | } 143 | 144 | # pragma mark KVC/KVO methods 145 | - (NSArray *) sha1s 146 | { 147 | [self doesNotRecognizeSelector: _cmd]; 148 | return NO; 149 | } 150 | 151 | - (NSUInteger) countOfSha1s { return [self numberOfObjects]; } 152 | 153 | - (NSString *) objectInSha1sAtIndex:(NSUInteger)i 154 | { 155 | [self doesNotRecognizeSelector: _cmd]; 156 | return NO; 157 | } 158 | 159 | - (NSArray *) CRCs 160 | { 161 | [self doesNotRecognizeSelector: _cmd]; 162 | return NO; 163 | } 164 | 165 | - (NSUInteger) countOfCRCs 166 | { 167 | [self doesNotRecognizeSelector: _cmd]; 168 | return NO; 169 | } 170 | 171 | - (NSData *) objectInCRCsAtIndex:(NSUInteger)i; 172 | { 173 | [self doesNotRecognizeSelector: _cmd]; 174 | return NO; 175 | } 176 | 177 | @end 178 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackIndexVersion1.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackIndexVersion1.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackIndex.h" 10 | 11 | @class GITPackReverseIndex; 12 | @interface GITPackIndexVersion1 : GITPackIndex 13 | { 14 | NSString * path; 15 | NSData * data; 16 | NSArray * offsets; 17 | GITPackReverseIndex *revIndex; 18 | } 19 | 20 | @property(readwrite,copy) NSString * path; 21 | @property(readwrite,retain) NSData * data; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackIndexVersion2.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackIndexVersion2.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackIndex.h" 10 | 11 | #define EXTENDED_OFFSET_FLAG (1 << 31) 12 | 13 | @class GITPackReverseIndex; 14 | 15 | @interface GITPackIndexVersion2 : GITPackIndex 16 | { 17 | NSString *path; 18 | NSData *data; 19 | NSArray *offsets; 20 | GITPackReverseIndex *revIndex; 21 | } 22 | 23 | @property(readwrite,copy) NSString * path; 24 | @property(readwrite,retain) NSData * data; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPackReverseIndex.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackReverseIndex.h 3 | // CocoaGit 4 | // 5 | // Created by Brian Chapados on 2/16/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class GITPackIndex; 12 | @interface GITPackReverseIndex : NSObject { 13 | GITPackIndex *index; 14 | CFMutableArrayRef offsets; 15 | NSUInteger size; 16 | } 17 | @property (nonatomic, readonly, assign) GITPackIndex *index; 18 | 19 | - (id) initWithPackIndex:(GITPackIndex *)packIndex; 20 | - (NSUInteger) indexWithOffset:(off_t)offset; 21 | - (off_t) nextOffsetWithOffset:(off_t)thisOffset; 22 | - (off_t) baseOffsetWithOffset:(off_t)theOffset; 23 | @end 24 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPlaceholderPackFile.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPlaceholderPackFile.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackFile.h" 10 | 11 | 12 | @interface GITPlaceholderPackFile : GITPackFile 13 | { 14 | } 15 | @end 16 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPlaceholderPackFile.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITPlaceholderPackFile.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPlaceholderPackFile.h" 10 | #import "GITUtilityBelt.h" 11 | 12 | static const char const kGITPackFileSignature[] = {'P', 'A', 'C', 'K'}; 13 | 14 | // Name of Range Start Length 15 | const NSRange kGITPackFileSignatureRange = { 0, 4 }; 16 | const NSRange kGITPackFileVersionRange = { 4, 4 }; 17 | 18 | @implementation GITPlaceholderPackFile 19 | 20 | - (id)initWithData:(NSData*)packData error:(NSError **)error; 21 | { 22 | if (! packData) 23 | return nil; 24 | 25 | uint8_t buf[4]; 26 | NSUInteger ver; 27 | NSString * errorDescription; 28 | NSZone * z = [self zone]; 29 | [self release]; 30 | 31 | [packData getBytes:buf range:kGITPackFileSignatureRange]; 32 | if (memcmp(buf, kGITPackFileSignature, kGITPackFileSignatureRange.length) != 0) { 33 | //NSString *errorDescription = [NSString stringWithFormat:NSLocalizedString(@"Data is not valid PACK format", "GITErrorPackFileInvalid"), thePath]; 34 | GITError(error, GITErrorPackFileInvalid, NSLocalizedString(@"Data is not valid PACK format", "GITErrorPackFileInvalid")); 35 | return nil; 36 | } 37 | 38 | // Its a valid PACK file 39 | memset(buf, 0x0, kGITPackFileSignatureRange.length); 40 | [packData getBytes:buf range:kGITPackFileVersionRange]; 41 | ver = integerFromBytes(buf, kGITPackFileVersionRange.length); 42 | 43 | switch (ver) 44 | { 45 | case 2: 46 | return [[GITPackFileVersion2 allocWithZone:z] initWithData:packData error:error]; 47 | default: 48 | errorDescription = [NSString stringWithFormat:NSLocalizedString(@"Pack version %lu not supported", @"GITErrorPackFileNotSupported"), ver]; 49 | GITError(error, GITErrorPackFileNotSupported, errorDescription); 50 | return nil; 51 | } 52 | } 53 | 54 | - (id)initWithPath:(NSString*)thePath error:(NSError **)error 55 | { 56 | uint8_t buf[4]; 57 | NSUInteger ver; 58 | NSString * errorDescription; 59 | NSZone * z = [self zone]; [self release]; 60 | NSData * data = [NSData dataWithContentsOfFile:thePath 61 | options:NSMappedRead 62 | error:error]; 63 | if (!data) 64 | return nil; 65 | 66 | // File opened successfully 67 | [data getBytes:buf range:kGITPackFileSignatureRange]; 68 | if (memcmp(buf, kGITPackFileSignature, kGITPackFileSignatureRange.length) != 0) { 69 | NSString *errorDescription = [NSString stringWithFormat:NSLocalizedString(@"File %@ is not a PACK file", "GITErrorPackFileInvalid"), thePath]; 70 | GITError(error, GITErrorPackFileInvalid, errorDescription); 71 | return nil; 72 | } 73 | 74 | // Its a valid PACK file 75 | memset(buf, 0x0, kGITPackFileSignatureRange.length); 76 | [data getBytes:buf range:kGITPackFileVersionRange]; 77 | ver = integerFromBytes(buf, kGITPackFileVersionRange.length); 78 | 79 | switch (ver) 80 | { 81 | case 2: 82 | return [[GITPackFileVersion2 allocWithZone:z] initWithPath:thePath error:error]; 83 | default: 84 | errorDescription = [NSString stringWithFormat:NSLocalizedString(@"Pack version %lu not supported", @"GITErrorPackFileNotSupported"), ver]; 85 | GITError(error, GITErrorPackFileNotSupported, errorDescription); 86 | return nil; 87 | } 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPlaceholderPackIndex.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPlaceholderPackIndex.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPackIndex.h" 10 | 11 | 12 | @interface GITPlaceholderPackIndex : GITPackIndex 13 | { 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /CocoaGit/Pack/GITPlaceholderPackIndex.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITPlaceholderPackIndex.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 04/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITPlaceholderPackIndex.h" 10 | #import "GITUtilityBelt.h" 11 | #import "GITErrors.h" 12 | 13 | static const char const kGITPackIndexMagicNumber[] = { '\377', 't', 'O', 'c' }; 14 | 15 | @implementation GITPlaceholderPackIndex 16 | - (id)initWithPath:(NSString*)thePath error:(NSError**)outError 17 | { 18 | uint8_t buf[4]; 19 | NSUInteger ver; 20 | NSString * description; 21 | NSFileManager * fileManager = [NSFileManager defaultManager]; 22 | NSZone * z = [self zone]; [self release]; 23 | 24 | if (! [fileManager isReadableFileAtPath:thePath]) { 25 | description = [NSString stringWithFormat:NSLocalizedString(@"File %@ not found",@"GITErrorFileNotFound (GITPackIndex)"), thePath]; 26 | GITError(outError, GITErrorFileNotFound, description); 27 | return nil; 28 | } 29 | 30 | NSData * data = [NSData dataWithContentsOfFile:thePath 31 | options:NSMappedRead 32 | error:outError]; 33 | if (!data) // Another type of error occurred 34 | return nil; 35 | 36 | // File opened successfully, read the first four bytes to see if 37 | // we are a version 1 index or a later version index. 38 | [data getBytes:buf range:NSMakeRange(0, 4)]; 39 | if (memcmp(buf, kGITPackIndexMagicNumber, 4) != 0) 40 | return [[GITPackIndexVersion1 allocWithZone:z] initWithPath:thePath error:outError]; 41 | 42 | // Its a v2+ index file 43 | memset(buf, 0x0, 4); 44 | [data getBytes:buf range:NSMakeRange(4, 4)]; 45 | ver = integerFromBytes(buf, 4); 46 | 47 | switch (ver) 48 | { 49 | case 2: 50 | return [[GITPackIndexVersion2 allocWithZone:z] initWithPath:thePath error:outError]; 51 | default: 52 | description = [NSString stringWithFormat:NSLocalizedString(@"Pack Index version %lu is not supported",@"GITErrorPackIndexUnsupportedVersion"), ver]; 53 | GITError(outError, GITErrorPackIndexUnsupportedVersion, description); 54 | return nil; 55 | } 56 | } 57 | @end -------------------------------------------------------------------------------- /CocoaGit/Refs/GITBranch.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITBranch.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class GITRepo, GITCommit; 12 | @interface GITBranch : NSObject 13 | { 14 | GITRepo * repo; 15 | NSString * name; 16 | } 17 | 18 | @property(readonly,copy) NSString * name; 19 | 20 | - (GITCommit*)head; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /CocoaGit/Refs/GITBranch.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITBranch.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 05/08/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITBranch.h" 10 | #import "GITRepo.h" 11 | #import "GITCommit.h" 12 | 13 | /*! \cond 14 | Make properties readwrite so we can use 15 | them within the class. 16 | */ 17 | @interface GITBranch () 18 | @property(readwrite,retain) GITRepo * repo; 19 | @property(readwrite,copy) NSString * name; 20 | @end 21 | /*! \endcond */ 22 | 23 | @implementation GITBranch 24 | @synthesize repo; 25 | @synthesize name; 26 | 27 | - (void) dealloc 28 | { 29 | [repo release], repo = nil; 30 | [name release], name = nil; 31 | [super dealloc]; 32 | } 33 | 34 | - (GITCommit*) head 35 | { 36 | for (NSDictionary *ref in [self.repo refs]) { 37 | if ([[ref objectForKey:@"name"] hasSuffix:self.name]) { 38 | return [self.repo commitWithSha1:[ref objectForKey:@"sha"]]; 39 | } 40 | } 41 | return nil; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /CocoaGit/Refs/GITRef.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITRef.h 3 | // CocoaGit 4 | // 5 | // Created by Brian Chapados on 2/10/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITRepo.h" 11 | 12 | @class GITRepo; 13 | @class GITCommit; 14 | 15 | @interface GITRef : NSObject { 16 | NSString *name; 17 | NSString *linkName; 18 | NSString *sha1; 19 | BOOL isLink; 20 | BOOL isPacked; 21 | } 22 | @property (nonatomic, copy) NSString *name; 23 | @property (nonatomic, copy) NSString *sha1; 24 | @property (nonatomic, copy) NSString *linkName; 25 | @property (nonatomic, assign) BOOL isLink; 26 | @property (nonatomic, assign) BOOL isPacked; 27 | 28 | + (id) refWithName:(NSString *)refName sha1:(NSString *)sha1String; 29 | + (id) refWithName:(NSString *)refName sha1:(NSString *)sha1String packed:(BOOL)refIsPacked; 30 | + (id) refWithContentsOfFile:(NSString *)aPath name:(NSString *)refName; 31 | + (id) refWithContentsOfFile:(NSString *)aPath; 32 | + (id) refWithPacketLine:(NSString *)packetLine; 33 | 34 | - (id) initWithName:(NSString *)refName sha1:(NSString *)refSha1; 35 | - (id) initWithName:(NSString *)refName sha1:(NSString *)refSha1 packed:(BOOL)refIsPacked; 36 | - (id) initWithName:(NSString *)refName sha1:(NSString *)refSha1 37 | linkName:(NSString *)refLink packed:(BOOL)refIsPacked; 38 | 39 | - (NSString *) shortName; 40 | - (GITCommit *) commitWithRepo:(GITRepo *)repo; 41 | @end -------------------------------------------------------------------------------- /CocoaGit/Store/GITCombinedStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITCombinedStore.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 24/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObjectStore.h" 11 | 12 | /*! A series of priority levels for use when adding stores to a GITCombinedStore 13 | */ 14 | typedef enum { 15 | GITHighPriority = 0, //!< Adds the store to the head of the list so it is checked first 16 | GITNormalPriority = 1, //!< Adds the store to the end of the list 17 | GITLowPriority = 2, //!< Adds the store to the end of the list 18 | } GITCombinedStorePriority; 19 | 20 | /*! Implements a store which is composed of other stores. 21 | * The GITCombinedStore allows the user to combine a selection of GITObjectStore subclasses into 22 | * a single store unit. The primary use would be for combining a GITFileStore with a GITPackStore 23 | * so that both loose file objects and packed objects can be accessed through one object. 24 | */ 25 | @interface GITCombinedStore : GITObjectStore 26 | { 27 | NSMutableArray * stores; 28 | GITObjectStore * recentStore; 29 | } 30 | 31 | @property(readonly,retain) NSMutableArray * stores; 32 | 33 | /*! Creates and returns a new combined store. 34 | * The newly created store will have no internal stores until you add them with 35 | * a call to -addStore: or -addStore:priority:. 36 | * \returns A new combined store 37 | */ 38 | - (id)init; 39 | 40 | /*! Creates and returns a new combined store with the provided stores. 41 | * The newly created store will be composed of the stores provided. 42 | * \param firstStore A variable nil terminated list of stores to add 43 | * to the receiver. The stores will be added with the Normal priority. 44 | * \return A new combined store 45 | */ 46 | - (id)initWithStores:(GITObjectStore*)firstStore, ...; 47 | 48 | /*! Adds a store to the receiver with the Normal priority. 49 | * \param store The GITObjectStore instance to add to the receiver 50 | */ 51 | - (void)addStore:(GITObjectStore*)store; 52 | 53 | /*! Adds a list of stores to the receiver with normal priority. 54 | * \param firstStore A variable nil terminated list of stores to add to the receiver 55 | */ 56 | - (void)addStores:(GITObjectStore*)firstStore, ...; 57 | 58 | /*! Adds a list of stores to the receiver with normal priority. 59 | * \param firstStore A variable nil terminated list of stores to add to the receiver 60 | * \param args Variable argument list of extra stores to add to the receiver 61 | */ 62 | - (void)addStores:(GITObjectStore*)firstStore args:(va_list)args; 63 | 64 | /*! Adds a store to the receiver with priority. 65 | * \param store The GITObjectStore instance to add to the receiver 66 | * \param priority The priority indicates where the list of stores the store 67 | * should be placed. If you want the store to be checked first then you can 68 | * pass a higher priority. 69 | * \see GITCombinedStorePriority 70 | */ 71 | - (void)addStore:(GITObjectStore*)store priority:(GITCombinedStorePriority)priority; 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /CocoaGit/Store/GITCombinedStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITCombinedStore.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 24/11/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITCombinedStore.h" 10 | 11 | /*! \cond */ 12 | @interface GITCombinedStore () 13 | @property(readwrite,retain) NSMutableArray * stores; 14 | @property(readwrite,assign) GITObjectStore * recentStore; 15 | @end 16 | /*! \endcond */ 17 | 18 | @implementation GITCombinedStore 19 | @synthesize stores; 20 | @synthesize recentStore; 21 | 22 | - (void) dealloc 23 | { 24 | [stores release], stores = nil; 25 | recentStore = nil; 26 | [super dealloc]; 27 | } 28 | 29 | - (id)init 30 | { 31 | return [self initWithStores:nil]; 32 | } 33 | - (id)initWithRoot:(NSString*)root 34 | { 35 | return [self initWithStores:nil]; 36 | } 37 | - (id)initWithRoot:(NSString*)root error:(NSError**)error 38 | { 39 | return [self initWithStores:nil]; 40 | } 41 | - (id)initWithStores:(GITObjectStore*)firstStore, ... 42 | { 43 | if (self = [super init]) 44 | { 45 | self.stores = [NSMutableArray array]; 46 | self.recentStore = nil; 47 | 48 | va_list args; 49 | va_start(args, firstStore); 50 | [self addStores:firstStore args:args]; 51 | va_end(args); 52 | } 53 | 54 | return self; 55 | } 56 | 57 | - (void)addStore:(GITObjectStore*)store 58 | { 59 | [self addStore:store priority:GITNormalPriority]; 60 | } 61 | - (void)addStores:(GITObjectStore*)firstStore, ... 62 | { 63 | va_list args; 64 | va_start(args, firstStore); 65 | [self addStores:firstStore args:args]; 66 | va_end(args); 67 | } 68 | - (void)addStores:(GITObjectStore*)firstStore args:(va_list)args 69 | { 70 | GITObjectStore * eachStore = firstStore; 71 | while (eachStore) { 72 | [self addStore:eachStore priority:GITNormalPriority]; 73 | eachStore = va_arg(args, GITObjectStore*); 74 | } 75 | } 76 | - (void)addStore:(GITObjectStore*)store priority:(GITCombinedStorePriority)priority 77 | { 78 | // High goes at the front, Normal and Low append to the end. 79 | switch (priority) 80 | { 81 | case GITHighPriority: 82 | [self.stores insertObject:store atIndex:0]; 83 | break; 84 | case GITNormalPriority: 85 | case GITLowPriority: 86 | [self.stores addObject:store]; 87 | break; 88 | } 89 | } 90 | - (NSData*)dataWithContentsOfObject:(NSString*)sha1 91 | { 92 | NSData * objectData = nil; 93 | if (self.recentStore) 94 | objectData = [self.recentStore dataWithContentsOfObject:sha1]; 95 | if (objectData) return objectData; 96 | 97 | for (GITObjectStore * store in self.stores) 98 | { 99 | objectData = [store dataWithContentsOfObject:sha1]; 100 | if (objectData) 101 | { 102 | self.recentStore = store; 103 | return objectData; 104 | } 105 | } 106 | 107 | return nil; 108 | } 109 | - (BOOL)loadObjectWithSha1:(NSString*)sha1 intoData:(NSData**)data 110 | type:(GITObjectType*)type error:(NSError**)error 111 | { 112 | NSError * undError = nil; 113 | 114 | if (recentStore != nil) { 115 | if ([self.recentStore loadObjectWithSha1:sha1 intoData:data type:type error:&undError]) 116 | return YES; 117 | 118 | if ([undError code] != GITErrorObjectNotFound) { 119 | GITError(error, [undError code], [undError localizedDescription]); 120 | return NO; 121 | } 122 | } 123 | 124 | for (GITObjectStore * store in self.stores) { 125 | if (store == self.recentStore) 126 | continue; 127 | 128 | if ([store loadObjectWithSha1:sha1 intoData:data type:type error:&undError]) { 129 | self.recentStore = store; 130 | return YES; 131 | } 132 | 133 | if ([undError code] != GITErrorObjectNotFound) { 134 | GITError(error, [undError code], [undError localizedDescription]); 135 | return NO; 136 | } 137 | } 138 | 139 | // If we've made it this far then the object can't be found 140 | NSString *errorDescription = [NSString stringWithFormat:NSLocalizedString(@"Object %@ not found", @"GITErrorObjectNotFound"), sha1]; 141 | GITError(error, GITErrorObjectNotFound, errorDescription); 142 | return NO; 143 | } 144 | - (BOOL)writeObject:(NSData*)data type:(GITObjectType)type error:(NSError**)error 145 | { 146 | // NOTE: For now we'll just pass it on to the first store object. 147 | return [[self.stores objectAtIndex:0] writeObject:data type:type error:error]; 148 | } 149 | 150 | @end 151 | -------------------------------------------------------------------------------- /CocoaGit/Store/GITFileStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITFileStore.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 07/10/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObjectStore.h" 11 | 12 | /*! Loose file object storage. 13 | * Accesses objects stored as compressed files in .git/objects 14 | * directory. 15 | */ 16 | @interface GITFileStore : GITObjectStore 17 | { 18 | NSString * objectsDir; //!< Path to the .git/objects directory 19 | } 20 | 21 | @property(readonly,copy) NSString * objectsDir; 22 | 23 | /*! Returns the path to the object in the objects directory. 24 | * \param sha1 The object reference to generate the path for. 25 | * \return Path to the object identified by sha1 26 | */ 27 | - (NSString*)stringWithPathToObject:(NSString*)sha1; 28 | @end 29 | -------------------------------------------------------------------------------- /CocoaGit/Store/GITObjectStore.m: -------------------------------------------------------------------------------- 1 | // 2 | // GITObjectStore.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 09/10/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "GITObjectStore.h" 10 | #import "NSData+Searching.h" 11 | 12 | @implementation GITObjectStore 13 | + (id) storeWithRoot:(NSString *)root; 14 | { 15 | return [[[self alloc] initWithRoot:root error:NULL] autorelease]; 16 | } 17 | 18 | + (id) storeWithRoot:(NSString *)root error:(NSError **)error; 19 | { 20 | return [[[self alloc] initWithRoot:root error:error] autorelease]; 21 | } 22 | 23 | - (id)initWithRoot:(NSString*)root 24 | { 25 | [self doesNotRecognizeSelector:_cmd]; 26 | [self release]; 27 | return nil; 28 | } 29 | - (id)initWithRoot:(NSString*)root error:(NSError**)error 30 | { 31 | [self doesNotRecognizeSelector:_cmd]; 32 | [self release]; 33 | return nil; 34 | } 35 | 36 | - (id)initWithPath:(NSString*)aPath error:(NSError**)error 37 | { 38 | [self doesNotRecognizeSelector:_cmd]; 39 | [self release]; 40 | return nil; 41 | } 42 | 43 | - (NSData*)dataWithContentsOfObject:(NSString*)sha1 44 | { 45 | [self doesNotRecognizeSelector:_cmd]; 46 | return nil; 47 | } 48 | - (BOOL)hasObjectWithSha1:(NSString*)sha1 49 | { 50 | [self doesNotRecognizeSelector:_cmd]; 51 | return NO; 52 | } 53 | - (BOOL)extractFromObject:(NSString*)sha1 type:(NSString**)type 54 | size:(NSUInteger*)size data:(NSData**)data 55 | { 56 | NSData * raw = [self dataWithContentsOfObject:sha1]; 57 | if (raw) 58 | { 59 | NSRange range = [raw rangeOfNullTerminatedBytesFrom:0]; 60 | NSData * meta = [raw subdataWithRange:range]; 61 | *data = [raw subdataFromIndex:range.length + 1]; 62 | 63 | NSString * metaStr = [[NSString alloc] initWithData:meta 64 | encoding:NSASCIIStringEncoding]; 65 | NSUInteger indexOfSpace = [metaStr rangeOfString:@" "].location; 66 | 67 | *type = [metaStr substringToIndex:indexOfSpace]; 68 | *size = (NSUInteger)[[metaStr substringFromIndex:indexOfSpace + 1] integerValue]; 69 | 70 | if (data && type && size) 71 | return YES; 72 | } 73 | 74 | return NO; 75 | } 76 | - (BOOL)loadObjectWithSha1:(NSString*)sha1 intoData:(NSData**)data 77 | type:(GITObjectType*)type error:(NSError**)error 78 | { 79 | [self doesNotRecognizeSelector: _cmd]; 80 | return NO; 81 | } 82 | - (BOOL)writeObject:(NSData*)data type:(GITObjectType)type error:(NSError**)error 83 | { 84 | [self doesNotRecognizeSelector: _cmd]; 85 | return NO; 86 | } 87 | @end 88 | -------------------------------------------------------------------------------- /CocoaGit/Store/GITPackStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITPackStore.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 07/10/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "GITObjectStore.h" 11 | 12 | @class GITPackFile; 13 | 14 | /*! Packed objects storage. 15 | * Accesses objects stored as in PACK files in 16 | * .git/objects/pack directory. 17 | * \internal 18 | * PACK files are do not independently represent 19 | * the objects of a repository. Instead each PACK 20 | * holds only the objects which were not already 21 | * stored within a PACK. 22 | * For this reason the GITPackStore must to keep a 23 | * reference to each PACK file within the packsDir 24 | * so that it may correctly find the objects which 25 | * are requested. To improve the speed of retrieval 26 | * some kind of caching should probably be done. 27 | * The two main options I can see are an NSDictionary 28 | * of SHA1 -> PACK mappings and a reference to the 29 | * last PACK which successfully returned an object. 30 | * The first method is primarily useful for repetitive 31 | * accesses of the same SHA, while possible it would 32 | * probably be a better idea to leave this option for 33 | * now and see how often a SHA is accessed. The other 34 | * method is useful for accessing objects which are 35 | * likely to be nearby to each other. This would be 36 | * the most useful as typical operation would involve 37 | * reading a Commit, accessing its Tree and the Tree 38 | * contents. These objects are all reasonably likely 39 | * to be contained within the same PACK file. 40 | * 41 | * Houston we have a problem 42 | * PACK files do not store the object data in a similar 43 | * way to loose files. Loose files include a type/size 44 | * meta header at the top of the loose file. The data 45 | * for an object in a PACK file is just the contents. 46 | * The type/size meta header information is not present 47 | * within the object data. Instead this information is 48 | * separate within the PACK file just before the object 49 | * data. This poses a problem for the current method of 50 | * extracting the object data from a store and creating 51 | * an instance of the correct class from that data. 52 | * This could require a fundamental re-engineering of 53 | * the way in which objects are retrieved from stores & 54 | * the way in which objects are instanciated from the 55 | * data retrieved from the stores. 56 | * 57 | * The main question is, how do we change it and into 58 | * what form? 59 | */ 60 | @interface GITPackStore : GITObjectStore 61 | { 62 | NSString * packsDir; //!< Path to .git/objects/pack directory. 63 | NSArray * packFiles; 64 | GITPackFile * lastReadPack; 65 | } 66 | 67 | @property(readonly,copy) NSString * packsDir; 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /CocoaGit/Store/GITRefStore.h: -------------------------------------------------------------------------------- 1 | // 2 | // GITRefStore.h 3 | // CocoaGit 4 | // 5 | // Created by chapbr on 4/7/09. 6 | // Copyright 2009 Brian Chapados. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class GITRepo, GITRef; 12 | 13 | @interface GITRefStore : NSObject { 14 | // properties 15 | NSString *rootDir; 16 | NSString *refsDir; 17 | NSString *packFile; 18 | NSString *headFile; 19 | 20 | // internal state 21 | NSMutableDictionary *cachedRefs; 22 | NSMutableArray *symbolicRefs; 23 | BOOL fetchedLoose; 24 | BOOL fetchedPacked; 25 | } 26 | @property (readwrite, copy) NSString *rootDir; 27 | @property (readwrite, copy) NSString *refsDir; 28 | @property (readwrite, copy) NSString *packFile; 29 | @property (readwrite, copy) NSString *headFile; 30 | 31 | - (id) initWithRepo:(GITRepo *)repo error:(NSError **)error; 32 | - (id) initWithRoot:(NSString *)aPath error:(NSError **)error; 33 | 34 | //- (id) initWithPath:(NSString *)aPath packFile:(NSString *)packedRefsFile error:(NSError **)error; 35 | 36 | - (GITRef *) head; 37 | - (GITRef *) refWithName:(NSString *)refName; 38 | - (GITRef *) refByResolvingSymbolicRef:(GITRef *)symRef; 39 | - (NSString *) sha1WithSymbolicRef:(GITRef *)symRef; 40 | 41 | - (NSArray *) refsWithPrefix:(NSString *)refPrefix; 42 | - (NSArray *) allRefs; 43 | - (NSArray *) branches; 44 | - (NSArray *) heads; 45 | - (NSArray *) tags; 46 | - (NSArray *) remotes; 47 | 48 | - (BOOL) writeRef:(GITRef *)aRef error:(NSError **)error; 49 | - (void) invalidateCachedRefs; 50 | @end -------------------------------------------------------------------------------- /CocoaGit/Util/NSCharacterSet+StringComparison.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSCharacterSet+StringComparison.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 25/03/2009. 6 | // Copyright 2009 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class NSString; 12 | @interface NSCharacterSet (StringComparison) 13 | - (BOOL)stringIsComposedOfCharactersInSet:(NSString*)string; 14 | @end 15 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSCharacterSet+StringComparison.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSCharacterSet+StringComparison.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 25/03/2009. 6 | // Copyright 2009 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "NSCharacterSet+StringComparison.h" 10 | #import 11 | 12 | @implementation NSCharacterSet (StringComparison) 13 | - (BOOL)stringIsComposedOfCharactersInSet:(NSString*)string 14 | { 15 | NSCharacterSet *inverted = [self invertedSet]; 16 | NSString *filtered = [[string componentsSeparatedByCharactersInSet:inverted] componentsJoinedByString:@""]; 17 | return [string isEqualToString:filtered]; 18 | } 19 | @end 20 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Compression.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Compression.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 29/06/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | // Methods extracted from source given at 9 | // http://www.cocoadev.com/index.pl?NSDataCategory 10 | // 11 | 12 | #import 13 | 14 | /*! Adds compression and decompression messages to NSData. 15 | * Methods extracted from source given at 16 | * http://www.cocoadev.com/index.pl?NSDataCategory 17 | */ 18 | @interface NSData (Compression) 19 | 20 | #pragma mark - 21 | #pragma mark Zlib Compression routines 22 | /*! Returns a data object containing a Zlib decompressed copy of the receivers contents. 23 | * \returns A data object containing a Zlib decompressed copy of the receivers contents. 24 | */ 25 | - (NSData *) zlibInflate; 26 | /*! Returns a data object containing a Zlib compressed copy of the receivers contents. 27 | * \returns A data object containing a Zlib compressed copy of the receivers contents. 28 | */ 29 | - (NSData *) zlibDeflate; 30 | 31 | #pragma mark - 32 | #pragma mark Gzip Compression routines 33 | /*! Returns a data object containing a Gzip decompressed copy of the receivers contents. 34 | * \returns A data object containing a Gzip decompressed copy of the receivers contents. 35 | */ 36 | - (NSData *) gzipInflate; 37 | /*! Returns a data object containing a Gzip compressed copy of the receivers contents. 38 | * \returns A data object containing a Gzip compressed copy of the receivers contents. 39 | */ 40 | - (NSData *) gzipDeflate; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Hashing.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Hashing.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 29/06/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | // Methods extracted from source given at 9 | // http://www.cocoadev.com/index.pl?NSDataCategory 10 | // 11 | 12 | #import 13 | 14 | @interface NSData (Hashing) 15 | 16 | #pragma mark - 17 | #pragma mark SHA1 Hashing routines 18 | /*! Returns the SHA1 digest of the receivers contents. 19 | * \return SHA1 digest of the receivers contents. 20 | */ 21 | - (NSData*) sha1Digest; 22 | 23 | /*! Returns a string with the SHA1 digest of the receivers contents. 24 | * \return String with the SHA1 digest of the receivers contents. 25 | */ 26 | - (NSString*) sha1DigestString; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Hashing.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Hashing.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 29/06/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | // Methods extracted from source given at 9 | // http://www.cocoadev.com/index.pl?NSDataCategory 10 | // 11 | // The original NSDataCategory used OpenSSL for the 12 | // hashing. This has been switched to CommonCrypto 13 | // due to its availability on both iPhone and Mac OS. 14 | // 15 | 16 | #import "NSData+Hashing.h" 17 | #include 18 | 19 | @implementation NSData (Hashing) 20 | 21 | #pragma mark - 22 | #pragma mark Hashing macros 23 | #define HEComputeDigest(method) \ 24 | CC_##method##_CTX ctx; \ 25 | unsigned char digest[CC_##method##_DIGEST_LENGTH]; \ 26 | CC_##method##_Init(&ctx); \ 27 | CC_##method##_Update(&ctx, [self bytes], [self length]); \ 28 | CC_##method##_Final(digest, &ctx); 29 | 30 | #define HEComputeDigestNSData(method) \ 31 | HEComputeDigest(method) \ 32 | return [NSData dataWithBytes:digest length:CC_##method##_DIGEST_LENGTH]; 33 | 34 | #define HEComputeDigestNSString(method) \ 35 | static char __HEHexDigits[] = "0123456789abcdef"; \ 36 | unsigned char digestString[2*CC_##method##_DIGEST_LENGTH]; \ 37 | unsigned int i; \ 38 | HEComputeDigest(method) \ 39 | for(i=0; i> 4]; \ 41 | digestString[2*i+1] = __HEHexDigits[digest[i] & 0x0f]; \ 42 | } \ 43 | return [NSString stringWithCString:(char *)digestString length:2*CC_##method##_DIGEST_LENGTH]; 44 | 45 | #pragma mark - 46 | #pragma mark SHA1 Hashing routines 47 | - (NSData*) sha1Digest 48 | { 49 | HEComputeDigestNSData(SHA1); 50 | } 51 | - (NSString*) sha1DigestString 52 | { 53 | HEComputeDigestNSString(SHA1); 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+HexDump.h: -------------------------------------------------------------------------------- 1 | /* 2 | NSData-HexDump 3 | Extracted From the SSCrypto project: 4 | http://www.septicus.com/SSCrypto/trunk/SSCrypto.m 5 | 6 | 7 | Copyright (c) 2003-2006, Septicus Software All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are 11 | met: 12 | 13 | * Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | * Neither the name of Septicus Software nor the names of its contributors 19 | may be used to endorse or promote products derived from this software 20 | without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 26 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #import 36 | 37 | @interface NSData (HexDump) 38 | - (NSString *)hexval; 39 | - (NSString *)hexdump; 40 | @end 41 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+HexDump.m: -------------------------------------------------------------------------------- 1 | /* 2 | NSData-HexDump 3 | Extracted From the SSCrypto project: 4 | http://www.septicus.com/SSCrypto/trunk/SSCrypto.m 5 | 6 | 7 | Copyright (c) 2003-2006, Septicus Software All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are 11 | met: 12 | 13 | * Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | * Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | * Neither the name of Septicus Software nor the names of its contributors 19 | may be used to endorse or promote products derived from this software 20 | without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 23 | IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24 | TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 26 | OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 29 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | */ 34 | 35 | #import "NSData+HexDump.h" 36 | 37 | @implementation NSData (HexDump) 38 | 39 | - (NSString *)hexval 40 | { 41 | NSMutableString *hex = [NSMutableString string]; 42 | unsigned char *bytes = (unsigned char *)[self bytes]; 43 | char temp[3]; 44 | int i = 0; 45 | 46 | for (i = 0; i < [self length]; i++) { 47 | temp[0] = temp[1] = temp[2] = 0; 48 | (void)sprintf(temp, "%02x", bytes[i]); 49 | [hex appendString:[NSString stringWithUTF8String:temp]]; 50 | } 51 | 52 | return hex; 53 | } 54 | 55 | - (NSString *)hexdump 56 | { 57 | NSMutableString *ret=[NSMutableString stringWithCapacity:[self length]*2]; 58 | /* dumps size bytes of *data to string. Looks like: 59 | * [0000] 75 6E 6B 6E 6F 77 6E 20 60 | * 30 FF 00 00 00 00 39 00 unknown 0.....9. 61 | * (in a single line of course) 62 | */ 63 | unsigned int size= [self length]; 64 | const unsigned char *p = [self bytes]; 65 | unsigned char c; 66 | int n; 67 | char bytestr[4] = {0}; 68 | char addrstr[10] = {0}; 69 | char hexstr[ 16*3 + 5] = {0}; 70 | char charstr[16*1 + 5] = {0}; 71 | for(n=1;n<=size;n++) { 72 | if (n%16 == 1) { 73 | /* store address for this line */ 74 | snprintf(addrstr, sizeof(addrstr), "%.4x", 75 | (unsigned int)((long)p-(long)self) ); 76 | } 77 | 78 | c = *p; 79 | if (isalnum(c) == 0) { 80 | c = '.'; 81 | } 82 | 83 | /* store hex str (for left side) */ 84 | snprintf(bytestr, sizeof(bytestr), "%02X ", *p); 85 | strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1); 86 | 87 | /* store char str (for right side) */ 88 | snprintf(bytestr, sizeof(bytestr), "%c", c); 89 | strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1); 90 | 91 | if(n%16 == 0) { 92 | /* line completed */ 93 | //printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); 94 | [ret appendString:[NSString stringWithFormat:@"[%4.4s] %-50.50s %s\n", 95 | addrstr, hexstr, charstr]]; 96 | hexstr[0] = 0; 97 | charstr[0] = 0; 98 | } else if(n%8 == 0) { 99 | /* half line: add whitespaces */ 100 | strncat(hexstr, " ", sizeof(hexstr)-strlen(hexstr)-1); 101 | strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1); 102 | } 103 | p++; /* next byte */ 104 | } 105 | 106 | if (strlen(hexstr) > 0) { 107 | /* print rest of buffer if not empty */ 108 | //printf("[%4.4s] %-50.50s %s\n", addrstr, hexstr, charstr); 109 | [ret appendString:[NSString stringWithFormat:@"[%4.4s] %-50.50s %s\n", 110 | addrstr, hexstr, charstr]]; 111 | } 112 | return ret; 113 | } 114 | @end 115 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Patching.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Patching.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 01/02/2009. 6 | // Copyright 2009 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSData (Patching) 13 | 14 | - (void)patchDeltaHeader:(NSData*)deltaData size:(unsigned long*)size 15 | position:(unsigned long*)position; 16 | - (NSData*)dataByPatchingWithDelta:(NSData*)delta; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Patching.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Patching.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 01/02/2009. 6 | // Copyright 2009 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "NSData+Patching.h" 10 | 11 | 12 | @implementation NSData (Patching) 13 | 14 | - (void)patchDeltaHeader:(NSData*)deltaData size:(unsigned long*)size position:(unsigned long*)position; 15 | { 16 | int shift = 0; 17 | unsigned char c; 18 | *size = 0; 19 | 20 | do { 21 | [deltaData getBytes:&c range:NSMakeRange((*position)++, 1)]; 22 | *size |= ((c & 0x7f) << shift); 23 | shift += 7; 24 | } while ( (c & 0x80) != 0 ); 25 | } 26 | 27 | - (NSData*)dataByPatchingWithDelta:(NSData*)deltaData; 28 | { 29 | unsigned long sourceSize, destSize, position = 0; 30 | unsigned long cp_off, cp_size; 31 | unsigned char c, d; 32 | 33 | [self patchDeltaHeader:deltaData size:&sourceSize position:&position]; 34 | destSize = 0; 35 | [self patchDeltaHeader:deltaData size:&destSize position:&position]; 36 | 37 | NSMutableData *destination = [NSMutableData dataWithCapacity:destSize]; 38 | 39 | while (position < [deltaData length]) { 40 | [deltaData getBytes:&c range:NSMakeRange(position++, 1)]; 41 | 42 | if ( (c & 0x80) != 0 ) { 43 | 44 | cp_off = 0; 45 | if ( 0 != (c & 0x01) ) { 46 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 47 | cp_off = d; 48 | } 49 | if ( 0 != (c & 0x02) ) { 50 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 51 | cp_off |= d << 8; 52 | } 53 | if ( 0 != (c & 0x04) ) { 54 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 55 | cp_off |= d << 16; 56 | } 57 | if ( 0 != (c & 0x08) ) { 58 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 59 | cp_off |= d << 24; 60 | } 61 | 62 | cp_size = 0; 63 | if ( 0 != (c & 0x10) ) { 64 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 65 | cp_size |= d; 66 | } 67 | if ( 0 != (c & 0x20) ) { 68 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 69 | cp_size |= d << 8; 70 | } 71 | if ( 0 != (c & 0x40) ) { 72 | [deltaData getBytes:&d range:NSMakeRange(position++, 1)]; 73 | cp_size |= d << 16; 74 | } 75 | if (cp_size == 0) 76 | cp_size = 0x10000; 77 | 78 | [destination appendData:[self subdataWithRange:NSMakeRange(cp_off, cp_size)]]; 79 | } else if ( c != 0 ) { 80 | [destination appendData:[deltaData subdataWithRange:NSMakeRange(position, c)]]; 81 | position += c; 82 | } else { 83 | [NSException raise:@"InvalidDeltaDataException" format:@"Delta data is invalid. Your packfile might be corrupt."]; 84 | NSLog(@"invalid delta data"); 85 | // invalid delta data 86 | } 87 | } 88 | 89 | return [[destination copy] autorelease]; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Searching.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Searching.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 17/07/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSData (Searching) 12 | 13 | /*! Returns the range of bytes up to the first occurrence of byte c from start. 14 | * \return Range of bytes up to the first occurrence of c from start. If c 15 | * can not be found then the NSRange.location will be set to NSNotFound. 16 | * \see memchr 17 | */ 18 | - (NSRange)rangeFrom:(NSInteger)start toByte:(NSInteger)c; 19 | 20 | /*! Returns the range of bytes up to the first NULL byte from start. 21 | * \return Range of bytes up to the first NULL from start. If no NULL 22 | * can be found then the NSRange.location will be set to NSNotFound. 23 | * \see memchr 24 | */ 25 | - (NSRange)rangeOfNullTerminatedBytesFrom:(NSInteger)start; 26 | 27 | /*! Returns a data object containing a copy of the receiver's bytes 28 | * that fall within the limits specified by a given index and the 29 | * end of the bytes. 30 | * \param index Start of the range which defines the limits to extract. 31 | * \return A data object containing a copy of the receiver's bytes 32 | * that fall within the limits of index and the end of the bytes. 33 | * \see -subdataWithRange: 34 | */ 35 | - (NSData*)subdataFromIndex:(NSUInteger)index; 36 | 37 | /*! Returns a data object containing a copy of the receiver's bytes 38 | * that fall within the first byte and index. 39 | * \param index End of the range which defines the limits to extract. 40 | * \return A data object containing a copy of the receiver's bytes 41 | * that fall within the first byte and index. 42 | * \see -subdataWithRange: 43 | */ 44 | - (NSData*)subdataToIndex:(NSUInteger)index; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSData+Searching.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Searching.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 17/07/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "NSData+Searching.h" 10 | #import // memchr 11 | 12 | @implementation NSData (Searching) 13 | 14 | - (NSRange)rangeFrom:(NSInteger)start toByte:(NSInteger)c; 15 | { 16 | const char *pdata = [self bytes]; 17 | NSUInteger len = [self length]; 18 | if (start < len) { 19 | char *end = memchr(pdata + start, c, len - start); 20 | if (end != NULL) 21 | return NSMakeRange (start, end - (pdata + start)); 22 | } 23 | return NSMakeRange(NSNotFound, 0); 24 | } 25 | 26 | - (NSRange)rangeOfNullTerminatedBytesFrom:(NSInteger)start 27 | { 28 | return [self rangeFrom:start toByte:0x00]; 29 | } 30 | 31 | - (NSData*)subdataFromIndex:(NSUInteger)anIndex 32 | { 33 | NSRange theRange = NSMakeRange(anIndex, [self length] - anIndex); 34 | return [self subdataWithRange:theRange]; 35 | } 36 | - (NSData*)subdataToIndex:(NSUInteger)anIndex 37 | { 38 | NSRange theRange = NSMakeRange(0, anIndex); 39 | return [self subdataWithRange:theRange]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSError-OBExtensions.h: -------------------------------------------------------------------------------- 1 | // Copyright 1997-2005, 2008 Omni Development, Inc. All rights reserved. 2 | // 3 | // This software may only be used and reproduced according to the 4 | // terms in the Omni Source License, which should be 5 | // distributed with this project and can also be found at 6 | // . 7 | // 8 | // **OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE** 9 | // 10 | // Omni Source Code software is available from The Omni Group on their 11 | // web site at [www.omnigroup.com](http://www.omnigroup.com/). 12 | // 13 | // Permission is hereby granted, free of charge, to any person 14 | // obtaining a copy of this software and associated documentation 15 | // files (the "Software"), to deal in the Software without 16 | // restriction, including without limitation the rights to use, copy, 17 | // modify, merge, publish, distribute, sublicense, and/or sell copies 18 | // of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // Any original copyright notices and this permission notice shall be 22 | // included in all copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 25 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | // SOFTWARE. 32 | // 33 | // $Header: svn+ssh://source.omnigroup.com/Source/svn/Omni/tags/OmniSourceRelease/2008-09-09/OmniGroup/Frameworks/OmniBase/NSError-OBExtensions.h 102857 2008-07-15 04:22:17Z bungi $ 34 | 35 | #import 36 | #import 37 | 38 | #if defined(__cplusplus) 39 | extern "C" { 40 | #endif 41 | 42 | #define GIT_BUNDLE_IDENTIFIER @"com.manicpanda.GIT" 43 | 44 | extern NSString * const OBUserCancelledActionErrorKey; 45 | extern NSString * const OBFileNameAndNumberErrorKey; 46 | 47 | @interface NSError (OBExtensions) 48 | 49 | - (BOOL)hasUnderlyingErrorDomain:(NSString *)domain code:(int)code; 50 | - (BOOL)causedByUserCancelling; 51 | 52 | - initWithPropertyList:(NSDictionary *)propertyList; 53 | - (NSDictionary *)toPropertyList; 54 | @end 55 | 56 | extern void OBErrorv(NSError **error, NSString *domain, int code, const char *fileName, unsigned int line, NSString *firstKey, va_list args); 57 | extern void _OBError(NSError **error, NSString *domain, int code, const char *fileName, unsigned int line, NSString *firstKey, ...); 58 | extern void _OBErrorWithDescription(NSError **error, NSString *domain, int code, const char *fileName, unsigned int line, NSString *message, ...); 59 | #ifdef OMNI_BUNDLE_IDENTIFIER 60 | // It is expected that -DOMNI_BUNDLE_IDENTIFIER=@"com.foo.bar" will be set when building your code. Build configurations make this easy since you can set it in the target's configuration and then have your Other C Flags have -DOMNI_BUNDLE_IDENTIFIER=@\"$(OMNI_BUNDLE_IDENTIFIER)\" and also use $(OMNI_BUNDLE_IDENTIFIER) in your Info.plist instead of duplicating it. 61 | #define OBError(error, code, description) _OBError(error, OMNI_BUNDLE_IDENTIFIER, code, __FILE__, __LINE__, NSLocalizedDescriptionKey, description, nil) 62 | #define OBErrorWithInfo(error, code, ...) _OBError(error, OMNI_BUNDLE_IDENTIFIER, code, __FILE__, __LINE__, ## __VA_ARGS__) 63 | #endif 64 | 65 | // Unlike the other routines in this file, but like all the other Foundation routines, this takes its key-value pairs with each value followed by its key. The disadvantage to this is that you can't easily have runtime-ignored values (the nil value is a terminator rather than being skipped). 66 | void OBErrorWithErrnoObjectsAndKeys(NSError **error, int errno_value, const char *function, NSString *argument, NSString *localizedDescription, ...); 67 | #define OBErrorWithErrno(error, errno_value, function, argument, localizedDescription) OBErrorWithErrnoObjectsAndKeys(error, errno_value, function, argument, localizedDescription, nil) 68 | 69 | 70 | #if defined(__cplusplus) 71 | } // extern "C" 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSFileManager+DirHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+DirHelper.h 3 | // ObjectiveGit 4 | 5 | 6 | #import 7 | 8 | @interface NSFileManager (DirHelpers) 9 | 10 | + (BOOL) directoryExistsAtPath:(NSString *) aPath; 11 | + (BOOL) directoryExistsAtURL:(NSURL *) aURL; 12 | + (BOOL) fileExistsAtPath:(NSString *) aPath; 13 | + (BOOL) fileExistsAtURL:(NSURL *) aURL; 14 | 15 | @end -------------------------------------------------------------------------------- /CocoaGit/Util/NSFileManager+DirHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSFileManager+DirHelper.m 3 | // ObjectiveGit 4 | 5 | 6 | #import "NSFileManager+DirHelper.h" 7 | 8 | @implementation NSFileManager (DirHelpers) 9 | 10 | + (BOOL) directoryExistsAtPath:(NSString *) aPath; 11 | { 12 | BOOL isDir; 13 | return [[self defaultManager] fileExistsAtPath:aPath isDirectory:&isDir] && isDir; 14 | } 15 | 16 | + (BOOL) directoryExistsAtURL:(NSURL *) aURL; 17 | { 18 | if (![aURL isFileURL]) 19 | return NO; 20 | 21 | NSString *aPath = [aURL path]; 22 | BOOL isDir; 23 | return [[self defaultManager] fileExistsAtPath:aPath isDirectory:&isDir] && isDir; 24 | } 25 | 26 | + (BOOL) fileExistsAtPath:(NSString *) aPath; 27 | { 28 | return [[self defaultManager] fileExistsAtPath:aPath]; 29 | } 30 | 31 | 32 | + (BOOL) fileExistsAtURL:(NSURL *) aURL; 33 | { 34 | if (![aURL isFileURL]) 35 | return NO; 36 | 37 | NSString *aPath = [aURL path]; 38 | return [[self defaultManager] fileExistsAtPath:aPath]; 39 | } 40 | @end 41 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSTimeZone+Offset.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimeZone+Offset.h 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 28/07/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NSTimeZone (Offset) 13 | 14 | /*! Creates and returns a time zone with the specified offset. 15 | * The string is broken down into the hour and minute components 16 | * which are then used to work out the number of seconds from GMT. 17 | * \param offset The timezone offset as a string such as "+0100" 18 | * \return A time zone with the specified offset 19 | * \see +timeZoneForSecondsFromGMT: 20 | */ 21 | + (id)timeZoneWithStringOffset:(NSString*)offset; 22 | 23 | /*! Returns the receivers offset as an HHMM formatted string. 24 | * \return The receivers offset as a string in HHMM format. 25 | */ 26 | - (NSString*)offsetString; 27 | @end 28 | -------------------------------------------------------------------------------- /CocoaGit/Util/NSTimeZone+Offset.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSTimeZone+Offset.m 3 | // CocoaGit 4 | // 5 | // Created by Geoffrey Garside on 28/07/2008. 6 | // Copyright 2008 ManicPanda.com. All rights reserved. 7 | // 8 | 9 | #import "NSTimeZone+Offset.h" 10 | 11 | static const unsigned short int HourInSeconds = 3600; 12 | static const unsigned short int MinuteInSeconds = 60; 13 | 14 | @implementation NSTimeZone (Offset) 15 | 16 | + (id)timeZoneWithStringOffset:(NSString*)offset 17 | { 18 | NSString * hours = [offset substringWithRange:NSMakeRange(1, 2)]; 19 | NSString * mins = [offset substringWithRange:NSMakeRange(3, 2)]; 20 | 21 | NSTimeInterval seconds = ([hours integerValue] * HourInSeconds) + ([mins integerValue] * MinuteInSeconds); 22 | if ([offset characterAtIndex:0] == '-') 23 | seconds = seconds * -1; 24 | 25 | return [self timeZoneForSecondsFromGMT:seconds]; 26 | } 27 | - (NSString*)offsetString 28 | { 29 | BOOL negative = NO; 30 | unsigned short int hours, mins; //!< Shouldn't ever be > 60 31 | 32 | NSTimeInterval seconds = [self secondsFromGMT]; 33 | if (seconds < 0) { 34 | negative = YES; 35 | seconds = seconds * -1; 36 | } 37 | 38 | hours = (NSInteger)seconds / HourInSeconds; 39 | mins = ((NSInteger)seconds % HourInSeconds) / MinuteInSeconds; 40 | 41 | return [NSString stringWithFormat:@"%c%02d%02d", 42 | negative ? '-' : '+', hours, mins]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /CocoaGit/Util/assertions.m: -------------------------------------------------------------------------------- 1 | // Copyright 1997-2005, 2008 Omni Development, Inc. All rights reserved. 2 | // 3 | // This software may only be used and reproduced according to the 4 | // terms in the Omni Source License, which should be 5 | // distributed with this project and can also be found at 6 | // . 7 | // 8 | // **OPEN PERMISSION TO USE AND REPRODUCE OMNI SOURCE CODE SOFTWARE** 9 | // 10 | // Omni Source Code software is available from The Omni Group on their 11 | // web site at [www.omnigroup.com](http://www.omnigroup.com/). 12 | // 13 | // Permission is hereby granted, free of charge, to any person 14 | // obtaining a copy of this software and associated documentation 15 | // files (the "Software"), to deal in the Software without 16 | // restriction, including without limitation the rights to use, copy, 17 | // modify, merge, publish, distribute, sublicense, and/or sell copies 18 | // of the Software, and to permit persons to whom the Software is 19 | // furnished to do so, subject to the following conditions: 20 | // 21 | // Any original copyright notices and this permission notice shall be 22 | // included in all copies or substantial portions of the Software. 23 | // 24 | // THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 25 | // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 | // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 | // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 | // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | // SOFTWARE. 32 | 33 | #import "assertions.h" 34 | #import 35 | #import // For getpid() 36 | 37 | // RCS_ID("$Header: svn+ssh://source.omnigroup.com/Source/svn/Omni/tags/OmniSourceRelease/2008-09-09/OmniGroup/Frameworks/OmniBase/assertions.m 102862 2008-07-15 05:14:37Z bungi $") 38 | 39 | #ifdef OMNI_ASSERTIONS_ON 40 | 41 | BOOL OBEnableExpensiveAssertions = NO; 42 | 43 | void OBLogAssertionFailure(const char *type, const char *expression, const char *file, unsigned int lineNumber) 44 | { 45 | fprintf(stderr, "%s failed: requires '%s', file %s, line %d\n", type, expression, file, lineNumber); 46 | } 47 | 48 | static NSString *OBShouldAbortOnAssertFailureEnabled = @"OBShouldAbortOnAssertFailureEnabled"; 49 | 50 | static void OBDefaultAssertionHandler(const char *type, const char *expression, const char *file, unsigned int lineNumber) 51 | { 52 | OBLogAssertionFailure(type, expression, file, lineNumber); 53 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 54 | if ([userDefaults boolForKey:OBShouldAbortOnAssertFailureEnabled]) 55 | abort(); 56 | else if (OBIsRunningUnitTests()) { 57 | // If we are running unit tests, abort on assertion failure. We could make assertions throw exceptions, but note that this wouldn't catch cases where you are using 'shouldRaise' and hit an assertion. 58 | #ifdef DEBUG 59 | // If we're failing in a debug build, give the developer a little time to connect in gdb before crashing 60 | fprintf(stderr, "You have 15 seconds to attach to pid %u in gdb...\n", getpid()); 61 | [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:15.0]]; 62 | #endif 63 | abort(); 64 | } 65 | } 66 | 67 | static OBAssertionFailureHandler currentAssertionHandler = OBDefaultAssertionHandler; 68 | void OBSetAssertionFailureHandler(OBAssertionFailureHandler handler) 69 | { 70 | if (handler) 71 | currentAssertionHandler = handler; 72 | else 73 | currentAssertionHandler = OBDefaultAssertionHandler; 74 | } 75 | 76 | void OBAssertFailed(const char *type, const char *expression, const char *file, unsigned int lineNumber) 77 | { 78 | currentAssertionHandler(type, expression, file, lineNumber); 79 | } 80 | 81 | #endif 82 | 83 | #if defined(OMNI_ASSERTIONS_ON) || defined(DEBUG) 84 | 85 | static void _OBAssertionLoad(void) __attribute__((constructor)); 86 | static void _OBAssertionLoad(void) 87 | { 88 | #ifdef OMNI_ASSERTIONS_ON 89 | OBEnableExpensiveAssertions = [[NSUserDefaults standardUserDefaults] boolForKey:@"OBEnableExpensiveAssertions"]; 90 | if (getenv("OBASSERT_NO_BANNER") == NULL) { 91 | fprintf(stderr, "*** Assertions are ON ***\n"); 92 | if (OBEnableExpensiveAssertions) 93 | fprintf(stderr, "*** Expensive assertions are ON ***\n"); 94 | } 95 | #elif DEBUG 96 | if (getenv("OBASSERT_NO_BANNER") == NULL) 97 | fprintf(stderr, "*** Assertions are OFF ***\n"); 98 | #endif 99 | } 100 | #endif 101 | -------------------------------------------------------------------------------- /Controllers/AppController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: AppController.h 4 | Abstract: UIApplication's delegate class, the central controller of the 5 | application. 6 | 7 | Version: 1.5 8 | 9 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 10 | ("Apple") in consideration of your agreement to the following terms, and your 11 | use, installation, modification or redistribution of this Apple software 12 | constitutes acceptance of these terms. If you do not agree with these terms, 13 | please do not use, install, modify or redistribute this Apple software. 14 | 15 | In consideration of your agreement to abide by the following terms, and subject 16 | to these terms, Apple grants you a personal, non-exclusive license, under 17 | Apple's copyrights in this original Apple software (the "Apple Software"), to 18 | use, reproduce, modify and redistribute the Apple Software, with or without 19 | modifications, in source and/or binary forms; provided that if you redistribute 20 | the Apple Software in its entirety and without modifications, you must retain 21 | this notice and the following text and disclaimers in all such redistributions 22 | of the Apple Software. 23 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 24 | to endorse or promote products derived from the Apple Software without specific 25 | prior written permission from Apple. Except as expressly stated in this notice, 26 | no other rights or licenses, express or implied, are granted by Apple herein, 27 | including but not limited to any patent rights that may be infringed by your 28 | derivative works or by other works in which the Apple Software may be 29 | incorporated. 30 | 31 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 32 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 33 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 35 | COMBINATION WITH YOUR PRODUCTS. 36 | 37 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 38 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 39 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 41 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 42 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 43 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | 45 | Copyright (C) 2008 Apple Inc. All Rights Reserved. 46 | 47 | */ 48 | 49 | #import "BrowserViewController.h" 50 | #import "ServerViewController.h" 51 | #import "GitHTTPConnection.h" 52 | 53 | //CLASS INTERFACES: 54 | 55 | @class HTTPServer; 56 | 57 | @interface AppController : NSObject 58 | { 59 | UIWindow* _window; 60 | UINavigationController *navigationController; 61 | UITabBarController *tabBarController; 62 | ServerViewController *serverViewController; 63 | HTTPServer *httpServer; 64 | NSString* gitDir; 65 | } 66 | 67 | @property (nonatomic, retain) UINavigationController *navigationController; 68 | @property (nonatomic, retain) UITabBarController *tabBarController; 69 | @property (nonatomic, retain) ServerViewController *serverViewController; 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Controllers/AppController.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: AppController.m 4 | Abstract: UIApplication's delegate class, the central controller of the 5 | application. 6 | 7 | Version: 1.5 8 | 9 | */ 10 | 11 | #import "AppController.h" 12 | #import "ProjectViewController.h" 13 | #import "ProjectController.h" 14 | #import "ServerViewController.h" 15 | #import "HTTPServer.h" 16 | #import "GitHTTPConnection.h" 17 | 18 | #define bonIdentifier @"git" 19 | 20 | //INTERFACES: 21 | 22 | @interface AppController () 23 | 24 | @property (assign, readwrite) NSString *gitDir; 25 | 26 | - (void) setup; 27 | 28 | @end 29 | 30 | //CLASS IMPLEMENTATIONS: 31 | 32 | @implementation AppController 33 | 34 | @synthesize gitDir; 35 | @synthesize navigationController; 36 | @synthesize tabBarController; 37 | @synthesize serverViewController; 38 | 39 | // creates [userDocs]/git path for git repos 40 | - (NSString *)getGitPath 41 | { 42 | NSArray *paths; 43 | NSString *gitPath = @""; 44 | NSString *tmpPath = @""; 45 | paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 46 | if ([paths count] > 0) { 47 | gitPath = [NSString stringWithString:[[paths objectAtIndex:0] stringByAppendingPathComponent:@"git"]]; 48 | 49 | BOOL isDir; 50 | NSFileManager *fm = [NSFileManager defaultManager]; 51 | if (![fm fileExistsAtPath:gitPath isDirectory:&isDir] && isDir) { 52 | [fm createDirectoryAtPath:gitPath attributes:nil]; 53 | } 54 | 55 | tmpPath = [NSString stringWithString:[[paths objectAtIndex:0] stringByAppendingPathComponent:@"gitTmp"]]; 56 | 57 | if (![fm fileExistsAtPath:tmpPath isDirectory:&isDir] && isDir) { 58 | [fm createDirectoryAtPath:tmpPath attributes:nil]; 59 | } 60 | } 61 | return gitPath; 62 | } 63 | 64 | - (void) applicationDidFinishLaunching:(UIApplication*)application 65 | { 66 | NSString * thisHostName = [[NSProcessInfo processInfo] hostName]; 67 | NSLog(@"hostname: %@", thisHostName); 68 | // Create a full-screen window 69 | _window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 70 | 71 | // getting the git path 72 | gitDir = [self getGitPath]; 73 | 74 | // Create and configure the navigation and view controllers 75 | ProjectController *pController = [[ProjectController alloc] init]; 76 | [pController readProjects:gitDir]; 77 | 78 | ProjectViewController *projectViewController = [[ProjectViewController alloc] initWithStyle:UITableViewStylePlain]; 79 | [projectViewController setProjectController:pController]; 80 | 81 | ServerViewController *serverController = [[ServerViewController alloc] init]; 82 | self.serverViewController = serverController; 83 | 84 | UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:projectViewController]; 85 | self.navigationController = aNavigationController; 86 | 87 | UITabBarController *atabBarController = [[UITabBarController alloc] init]; 88 | NSArray *vc = [NSArray arrayWithObjects:navigationController, serverViewController, nil]; 89 | [atabBarController setViewControllers:vc animated:NO]; 90 | self.tabBarController = atabBarController; 91 | 92 | // start the server 93 | httpServer = [HTTPServer new]; 94 | [httpServer setType:@"_http._tcp."]; 95 | [httpServer setConnectionClass:[GitHTTPConnection class]]; 96 | [httpServer setDocumentRoot:[NSURL fileURLWithPath:gitDir]]; 97 | [httpServer setPort:8082]; 98 | 99 | NSError *error; 100 | if(![httpServer start:&error]) 101 | { 102 | NSLog(@"Error starting HTTP Server: %@", error); 103 | } 104 | 105 | // Configure and show the window 106 | [_window addSubview:tabBarController.view]; 107 | [_window makeKeyAndVisible]; 108 | 109 | [projectViewController release]; 110 | [aNavigationController release]; 111 | 112 | [self setup]; 113 | } 114 | 115 | - (void) dealloc 116 | { 117 | NSLog(@"dealloc"); 118 | [_window release]; 119 | [super dealloc]; 120 | } 121 | 122 | - (void) setup { 123 | // TODO: setup the http server 124 | NSLog(@"Setup"); 125 | 126 | gitDir = [self getGitPath]; 127 | 128 | BOOL isDir=NO; 129 | NSFileManager *fileManager = [NSFileManager defaultManager]; 130 | if ([fileManager fileExistsAtPath:gitDir isDirectory:&isDir] && isDir) { 131 | NSEnumerator *e = [[fileManager directoryContentsAtPath:gitDir] objectEnumerator]; 132 | NSString *thisDir; 133 | while ( (thisDir = [e nextObject]) ) { 134 | NSLog(@"announce:%@", thisDir); 135 | // TODO: announce http over bonjour 136 | } 137 | } 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /Controllers/BrowserViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: BrowserViewController.h 4 | Abstract: 5 | View controller for the service instance list. 6 | This object manages a NSNetServiceBrowser configured to look for Bonjour 7 | services. 8 | It has an array of NSNetService objects that are displayed in a table view. 9 | When the service browser reports that it has discovered a service, the 10 | corresponding NSNetService is added to the array. 11 | When a service goes away, the corresponding NSNetService is removed from the 12 | array. 13 | Selecting an item in the table view asynchronously resolves the corresponding 14 | net service. 15 | When that resolution completes, the delegate is called with the corresponding 16 | NSNetService. 17 | 18 | 19 | Version: 1.5 20 | 21 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 22 | ("Apple") in consideration of your agreement to the following terms, and your 23 | use, installation, modification or redistribution of this Apple software 24 | constitutes acceptance of these terms. If you do not agree with these terms, 25 | please do not use, install, modify or redistribute this Apple software. 26 | 27 | In consideration of your agreement to abide by the following terms, and subject 28 | to these terms, Apple grants you a personal, non-exclusive license, under 29 | Apple's copyrights in this original Apple software (the "Apple Software"), to 30 | use, reproduce, modify and redistribute the Apple Software, with or without 31 | modifications, in source and/or binary forms; provided that if you redistribute 32 | the Apple Software in its entirety and without modifications, you must retain 33 | this notice and the following text and disclaimers in all such redistributions 34 | of the Apple Software. 35 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 36 | to endorse or promote products derived from the Apple Software without specific 37 | prior written permission from Apple. Except as expressly stated in this notice, 38 | no other rights or licenses, express or implied, are granted by Apple herein, 39 | including but not limited to any patent rights that may be infringed by your 40 | derivative works or by other works in which the Apple Software may be 41 | incorporated. 42 | 43 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 44 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 45 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 46 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 47 | COMBINATION WITH YOUR PRODUCTS. 48 | 49 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 50 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 51 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 53 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 54 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 55 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 | 57 | Copyright (C) 2008 Apple Inc. All Rights Reserved. 58 | 59 | */ 60 | 61 | #import 62 | #import 63 | 64 | @class BrowserViewController; 65 | 66 | @protocol BrowserViewControllerDelegate 67 | @required 68 | // This method will be invoked when the user selects one of the service instances from the list. 69 | // The ref parameter will be the selected (already resolved) instance or nil if the user taps the 'Cancel' button (if shown). 70 | - (void) browserViewController:(BrowserViewController*)bvc didResolveInstance:(NSNetService*)ref; 71 | @end 72 | 73 | @interface BrowserViewController : UITableViewController { 74 | 75 | @private 76 | id _delegate; 77 | NSString* _searchingForServicesString; 78 | NSString* _ownName; 79 | NSNetService* _ownEntry; 80 | BOOL _showDisclosureIndicators; 81 | NSMutableArray* _services; 82 | NSNetServiceBrowser* _netServiceBrowser; 83 | NSNetService* _currentResolve; 84 | NSTimer* _timer; 85 | BOOL _needsActivityIndicator; 86 | BOOL _initialWaitOver; 87 | } 88 | 89 | @property (nonatomic, assign) id delegate; 90 | @property (nonatomic, copy) NSString* searchingForServicesString; 91 | @property (nonatomic, copy) NSString* ownName; 92 | 93 | - (id)initWithTitle:(NSString *)title showDisclosureIndicators:(BOOL)showDisclosureIndicators showCancelButton:(BOOL)showCancelButton; 94 | - (BOOL)searchForServicesOfType:(NSString *)type inDomain:(NSString *)domain; 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /Controllers/CommitDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommitDetailViewController.h 3 | // iGitHub 4 | // 5 | // Created by Scott Chacon on 9/29/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "Git.h" 11 | 12 | @interface CommitDetailViewController : UITableViewController { 13 | GITRepo *gitRepo; 14 | GITCommit *gitCommit; 15 | } 16 | 17 | @property (nonatomic, retain) GITRepo *gitRepo; 18 | @property (nonatomic, retain) GITCommit *gitCommit; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Controllers/CommitsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // CommitsViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "Git.h" 8 | 9 | @interface CommitsViewController : UITableViewController { 10 | GITRepo *gitRepo; 11 | NSString *gitRef; 12 | NSString *gitSha; 13 | NSMutableArray *commitList; 14 | } 15 | 16 | @property (nonatomic, retain) GITRepo *gitRepo; 17 | @property (nonatomic, retain) NSString *gitRef; 18 | @property (nonatomic, retain) NSString *gitSha; 19 | @property (nonatomic, retain) NSMutableArray *commitList; 20 | 21 | - (UITableViewCell *)tableviewCellWithReuseIdentifier:(NSString *)identifier; 22 | - (void)configureCell:(UITableViewCell *)cell forIndexPath:(NSIndexPath *)indexPath; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Controllers/GitHTTPConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // This class was created by Nonnus, 3 | // who graciously decided to share it with the CocoaHTTPServer community. 4 | // 5 | 6 | #import 7 | #import "HTTPConnection.h" 8 | 9 | 10 | @interface GitHTTPConnection : HTTPConnection 11 | { 12 | NSString* gitService; 13 | NSFileHandle* packfile; 14 | } 15 | 16 | - (BOOL)isBrowseable:(NSString *)path; 17 | - (NSString *)createBrowseableIndex:(NSString *)path; 18 | 19 | - (NSObject *)indexPage; 20 | - (NSObject *)plainResponse:(NSString *)project path:(NSString *)path; 21 | 22 | - (NSObject *)advertiseRefs:(NSString *)repository; 23 | 24 | - (NSObject *)receivePack:(NSString *)project; 25 | - (NSObject *)uploadPack:(NSString *)project; 26 | 27 | - (NSString*) prependPacketLine:(NSString*) info; 28 | - (NSData*) packetData:(NSString*) info; 29 | 30 | @end -------------------------------------------------------------------------------- /Controllers/ProjectController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | 8 | @interface ProjectController : NSObject { 9 | NSMutableArray *list; 10 | } 11 | 12 | - (void)readProjects:(NSString *)projectPath; 13 | - (unsigned)countOfList; 14 | - (id)objectInListAtIndex:(unsigned)theIndex; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Controllers/ProjectController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectController.h" 7 | #import "Git.h" 8 | 9 | @interface ProjectController () 10 | @property (nonatomic, copy, readwrite) NSMutableArray *list; 11 | @end 12 | 13 | @implementation ProjectController 14 | 15 | @synthesize list; 16 | 17 | // Custom set accessor to ensure the new list is mutable 18 | - (void)readProjects:(NSString *)projectPath 19 | { 20 | NSLog(@"READ PROJECTS:%@", projectPath); 21 | BOOL isDir=NO; 22 | [list release]; 23 | list = [[NSMutableArray alloc] init]; 24 | NSFileManager *fileManager = [NSFileManager defaultManager]; 25 | if ([fileManager fileExistsAtPath:projectPath isDirectory:&isDir] && isDir) { 26 | NSEnumerator *e = [[fileManager directoryContentsAtPath:projectPath] objectEnumerator]; 27 | NSString *thisDir; 28 | while ( (thisDir = [e nextObject]) ) { 29 | NSString *dir = [projectPath stringByAppendingPathComponent:thisDir]; 30 | GITRepo* git = [[GITRepo alloc] init]; 31 | [git initWithRoot:dir]; 32 | [git setDesc:thisDir]; 33 | [list addObject:git]; 34 | } 35 | } 36 | } 37 | 38 | // Accessor methods for list 39 | - (unsigned)countOfList { 40 | return [list count]; 41 | } 42 | 43 | - (id)objectInListAtIndex:(unsigned)theIndex { 44 | return [list objectAtIndex:theIndex]; 45 | } 46 | 47 | - (void)dealloc { 48 | [list release]; 49 | [super dealloc]; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Controllers/ProjectDetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectDetailViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "Git.h" 8 | 9 | @interface ProjectDetailViewController : UITableViewController { 10 | GITRepo *detailItem; 11 | } 12 | 13 | @property (nonatomic, retain) GITRepo *detailItem; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Controllers/ProjectDetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectDetailViewController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectDetailViewController.h" 7 | #import "CommitsViewController.h" 8 | #import "Git.h" 9 | 10 | @implementation ProjectDetailViewController 11 | 12 | @synthesize detailItem; 13 | 14 | 15 | - (void)viewWillAppear:(BOOL)animated { 16 | // Update the view with current data before it is displayed 17 | [super viewWillAppear:animated]; 18 | 19 | // Scroll the table view to the top before it appears 20 | [self.tableView reloadData]; 21 | [self.tableView setContentOffset:CGPointZero animated:NO]; 22 | self.title = [detailItem desc]; 23 | } 24 | 25 | // Standard table view data source and delegate methods 26 | 27 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 28 | // There are two sections, for info and stats 29 | return 2; 30 | } 31 | 32 | 33 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 34 | 35 | NSInteger rows = 0; 36 | switch (section) { 37 | case 0: 38 | // For project data, there is name 39 | rows = 1; 40 | break; 41 | case 1: 42 | // For the branches section, there is size 43 | rows = [[detailItem branches] count]; 44 | break; 45 | default: 46 | break; 47 | } 48 | return rows; 49 | } 50 | 51 | 52 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 53 | 54 | static NSString *CellIdentifier = @"tvc"; 55 | 56 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 57 | if (cell == nil) { 58 | cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease]; 59 | //cell.selectionStyle = UITableViewCellSelectionStyleNone; 60 | } 61 | 62 | NSString *cellText = nil; 63 | 64 | switch (indexPath.section) { 65 | case 0: 66 | cellText = [detailItem desc]; 67 | break; 68 | case 1: 69 | cellText = [[[detailItem branches] objectAtIndex:indexPath.row] name]; 70 | break; 71 | default: 72 | break; 73 | } 74 | 75 | cell.text = cellText; 76 | return cell; 77 | } 78 | 79 | 80 | /* 81 | Provide section titles 82 | HIG note: In this case, since the content of each section is obvious, there's probably no need to provide a title, but the code is useful for illustration. 83 | */ 84 | - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 85 | 86 | NSString *title = nil; 87 | switch (section) { 88 | case 0: 89 | title = NSLocalizedString(@"Project Info", @"Git Project Information"); 90 | break; 91 | case 1: 92 | title = NSLocalizedString(@"Branches", @"Git Project Refs"); 93 | break; 94 | default: 95 | break; 96 | } 97 | return title; 98 | } 99 | 100 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 101 | CommitsViewController *commitsViewController = [[CommitsViewController alloc] initWithStyle:UITableViewStylePlain]; 102 | GITRef *ref = [[detailItem branches] objectAtIndex:indexPath.row]; 103 | 104 | commitsViewController.gitRepo = detailItem; 105 | commitsViewController.gitRef = [ref name]; 106 | commitsViewController.gitSha = [ref sha1]; 107 | 108 | // Push the commit view controller 109 | [[self navigationController] pushViewController:commitsViewController animated:YES]; 110 | [commitsViewController release]; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /Controllers/ProjectViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectViewController.h 3 | // iGitHub 4 | // 5 | 6 | #import 7 | #import "ProjectController.h" 8 | #import "Git.h" 9 | #import "GITRef.h" 10 | 11 | @interface ProjectViewController : UITableViewController { 12 | ProjectController *projectController; 13 | } 14 | 15 | @property (nonatomic, retain) ProjectController *projectController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Controllers/ProjectViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectViewController.m 3 | // iGitHub 4 | // 5 | 6 | #import "ProjectViewController.h" 7 | #import "ProjectDetailViewController.h" 8 | 9 | @implementation ProjectViewController 10 | 11 | @synthesize projectController; 12 | 13 | - (id)initWithStyle:(UITableViewStyle)style { 14 | if ((self = [super initWithStyle:style])) { 15 | self.title = NSLocalizedString(@"Projects", @"My Local Git Project List"); 16 | self.tabBarItem.image = [UIImage imageNamed:@"servericon.png"]; 17 | } 18 | return self; 19 | } 20 | 21 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 22 | return 1; 23 | } 24 | 25 | 26 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 27 | return [projectController countOfList]; 28 | } 29 | 30 | 31 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 32 | 33 | static NSString *MyIdentifier = @"MyIdentifier"; 34 | 35 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 36 | if (cell == nil) { 37 | cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease]; 38 | } 39 | 40 | // Get the object to display and set the value in the cell 41 | GITRepo *itemAtIndex = [projectController objectInListAtIndex:indexPath.row]; 42 | cell.text = [itemAtIndex desc]; 43 | return cell; 44 | } 45 | 46 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 47 | 48 | ProjectDetailViewController *detailViewController = [[ProjectDetailViewController alloc] initWithStyle:UITableViewStyleGrouped]; 49 | detailViewController.detailItem = [projectController objectInListAtIndex:indexPath.row]; 50 | 51 | // Push the detail view controller 52 | [[self navigationController] pushViewController:detailViewController animated:YES]; 53 | [detailViewController release]; 54 | } 55 | 56 | /* 57 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 58 | 59 | if (editingStyle == UITableViewCellEditingStyleDelete) { 60 | } 61 | if (editingStyle == UITableViewCellEditingStyleInsert) { 62 | } 63 | } 64 | */ 65 | /* 66 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 67 | return YES; 68 | } 69 | */ 70 | /* 71 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { 72 | } 73 | */ 74 | /* 75 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { 76 | return YES; 77 | } 78 | */ 79 | 80 | 81 | - (void)dealloc { 82 | [super dealloc]; 83 | } 84 | 85 | 86 | - (void)viewDidLoad { 87 | [super viewDidLoad]; 88 | } 89 | 90 | 91 | - (void)viewWillAppear:(BOOL)animated { 92 | [super viewWillAppear:animated]; 93 | } 94 | 95 | - (void)viewDidAppear:(BOOL)animated { 96 | [super viewDidAppear:animated]; 97 | } 98 | 99 | - (void)viewWillDisappear:(BOOL)animated { 100 | } 101 | 102 | - (void)viewDidDisappear:(BOOL)animated { 103 | } 104 | 105 | - (void)didReceiveMemoryWarning { 106 | [super didReceiveMemoryWarning]; 107 | } 108 | 109 | 110 | @end 111 | 112 | -------------------------------------------------------------------------------- /Controllers/ServerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ServerViewController.h 3 | // iGitHub 4 | // 5 | // Created by Scott Chacon on 9/30/08. 6 | // Copyright 2008 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface ServerViewController : UIViewController { 13 | UILabel* serverNameLabel; 14 | } 15 | 16 | @property (nonatomic, retain) UILabel* serverNameLabel; 17 | 18 | - (void)setServerName:(NSString *)string; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Controllers/ServerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ServerViewController.m 3 | // iGitHub 4 | // 5 | 6 | 7 | #import "ServerViewController.h" 8 | 9 | #define kOffset 5.0 10 | 11 | @implementation ServerViewController 12 | 13 | @synthesize serverNameLabel; 14 | 15 | -(id)init { 16 | self = [super init]; 17 | if (self) { 18 | self.title = @"Server"; 19 | self.tabBarItem.image = [UIImage imageNamed:@"rssicon.png"]; 20 | } 21 | return self; 22 | } 23 | 24 | -(void)loadView { 25 | NSLog(@"First View"); 26 | UIView *firstView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"server.png"]]; 27 | [firstView setAutoresizingMask:UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth]; 28 | [firstView setBackgroundColor:[UIColor yellowColor]]; 29 | self.view = firstView; 30 | [firstView release]; 31 | 32 | UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; 33 | [label setTextAlignment:UITextAlignmentCenter]; 34 | [label setFont:[UIFont systemFontOfSize:18.0]]; 35 | [label setTextColor:[UIColor blackColor]]; 36 | [label setBackgroundColor:[UIColor clearColor]]; 37 | label.text = @"Git Server Listening On"; 38 | label.numberOfLines = 1; 39 | [label sizeToFit]; 40 | label.frame = CGRectMake(0.0, 200.0, 320.0, label.frame.size.height); 41 | [self.view addSubview:label]; 42 | 43 | NSString *hostName = [[NSProcessInfo processInfo] hostName]; 44 | if ([hostName hasSuffix:@".local"]) { 45 | hostName = [hostName substringToIndex:([hostName length] - 6)]; 46 | } 47 | label = [[UILabel alloc] initWithFrame:CGRectZero]; 48 | [label setTextAlignment:UITextAlignmentCenter]; 49 | [label setFont:[UIFont systemFontOfSize:28.0]]; 50 | [label setTextColor:[UIColor blackColor]]; 51 | [label setBackgroundColor:[UIColor clearColor]]; 52 | label.text = [NSString stringWithFormat:@"git://%@/", hostName]; 53 | label.numberOfLines = 1; 54 | [label sizeToFit]; 55 | label.frame = CGRectMake(0.0, 250.0, 320.0, label.frame.size.height); 56 | self.serverNameLabel = label; 57 | [self.view addSubview:self.serverNameLabel]; 58 | } 59 | 60 | - (void)setServerName:(NSString *)string { 61 | [self.serverNameLabel setText:string]; 62 | } 63 | 64 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 65 | // Return YES for supported orientations 66 | return (interfaceOrientation == UIInterfaceOrientationPortrait); 67 | } 68 | 69 | 70 | - (void)didReceiveMemoryWarning { 71 | [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview 72 | // Release anything that's not essential, such as cached data 73 | } 74 | 75 | 76 | - (void)dealloc { 77 | [super dealloc]; 78 | } 79 | 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /Git/ObjGit.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGit.h 3 | // ObjGit 4 | // 5 | 6 | //#import 7 | //#import 8 | //#include 9 | 10 | #import 11 | #import "ObjGitObject.h" 12 | 13 | @interface ObjGit : NSObject { 14 | NSString* gitDirectory; 15 | NSString* gitName; 16 | } 17 | 18 | @property(copy, readwrite) NSString *gitDirectory; 19 | @property(copy, readwrite) NSString *gitName; 20 | 21 | - (BOOL) openRepo:(NSString *)dirPath; 22 | - (BOOL) ensureGitPath; 23 | - (void) initGitRepo; 24 | - (NSArray *) getAllRefs; 25 | 26 | - (NSString *) writeObject:(NSData *)objectData withType:(NSString *)type withSize:(int)size; 27 | - (void) updateRef:(NSString *)refName toSha:(NSString *)toSha; 28 | 29 | - (NSMutableArray *) getCommitsFromSha:(NSString *)shaValue withLimit:(int)commitSize; 30 | - (NSString *) getLooseObjectPathBySha:(NSString *)shaValue; 31 | - (BOOL) hasObject: (NSString *)sha1; 32 | - (ObjGitObject *) getObjectFromSha:(NSString *)sha1; 33 | 34 | + (int) isAlpha:(unsigned char)n ; 35 | + (int) gitUnpackHex:(const unsigned char *)rawsha fillSha:(char *)sha1; 36 | + (int) gitPackHex:(const char *)sha1 fillRawSha:(unsigned char *)rawsha; 37 | 38 | @end -------------------------------------------------------------------------------- /Git/ObjGitCommit.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitCommit.h 3 | // ObjGit 4 | // 5 | 6 | #import 7 | #import "ObjGitObject.h" 8 | 9 | @interface ObjGitCommit : NSObject { 10 | NSString *sha; 11 | NSArray *parentShas; 12 | NSString *treeSha; 13 | NSString *author; 14 | NSString *author_email; 15 | NSDate *authored_date; 16 | NSString *committer; 17 | NSString *committer_email; 18 | NSDate *committed_date; 19 | NSString *message; 20 | ObjGitObject *git_object; 21 | } 22 | 23 | @property(copy, readwrite) NSString *sha; 24 | @property(copy, readwrite) NSArray *parentShas; 25 | @property(copy, readwrite) NSString *treeSha; 26 | @property(copy, readwrite) NSString *author; 27 | @property(copy, readwrite) NSString *author_email; 28 | @property(copy, readwrite) NSDate *authored_date; 29 | @property(copy, readwrite) NSString *committer; 30 | @property(copy, readwrite) NSString *committer_email; 31 | @property(retain, readwrite) NSDate *committed_date; 32 | @property(assign, readwrite) NSString *message; 33 | @property(assign, readwrite) ObjGitObject *git_object; 34 | 35 | - (id) initFromGitObject:(ObjGitObject *)gitObject; 36 | - (id) initFromRaw:(NSData *)rawData withSha:(NSString *)shaValue; 37 | - (void) parseContent; 38 | - (void) logObject; 39 | - (NSArray *) authorArray; 40 | - (NSArray *) parseAuthorString:(NSString *)authorString withType:(NSString *)typeString; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Git/ObjGitCommit.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitCommit.m 3 | // ObjGit 4 | // 5 | 6 | #import "ObjGitObject.h" 7 | #import "ObjGitCommit.h" 8 | 9 | @implementation ObjGitCommit 10 | 11 | @synthesize parentShas; 12 | @synthesize treeSha; 13 | @synthesize author; 14 | @synthesize author_email; 15 | @synthesize authored_date; 16 | @synthesize committer; 17 | @synthesize committer_email; 18 | @synthesize committed_date; 19 | @synthesize message; 20 | @synthesize git_object; 21 | @synthesize sha; 22 | 23 | - (id) initFromGitObject:(ObjGitObject *)gitObject { 24 | self = [super init]; 25 | self.sha = [gitObject sha]; 26 | self.git_object = gitObject; 27 | [self parseContent]; 28 | return self; 29 | } 30 | 31 | - (id) initFromRaw:(NSData *)rawData withSha:(NSString *)shaValue 32 | { 33 | self = [super init]; 34 | self.git_object = [[ObjGitObject alloc] initFromRaw:rawData withSha:shaValue]; 35 | self.sha = shaValue; 36 | [self parseContent]; 37 | //[self logObject]; 38 | return self; 39 | } 40 | 41 | - (void) logObject 42 | { 43 | NSLog(@"tree : %@", treeSha); 44 | NSLog(@"author : %@, %@ : %@", author, author_email, authored_date); 45 | NSLog(@"committer: %@, %@ : %@", committer, committer_email, committed_date); 46 | NSLog(@"parents : %@", parentShas); 47 | NSLog(@"message : %@", message); 48 | } 49 | 50 | - (NSArray *) authorArray 51 | { 52 | return [NSArray arrayWithObjects:self.author, self.author_email, self.authored_date, nil]; 53 | } 54 | 55 | - (void) parseContent 56 | { 57 | // extract parent shas, tree sha, author/committer info, message 58 | NSArray *lines = [self.git_object.contents componentsSeparatedByString:@"\n"]; 59 | NSEnumerator *enumerator; 60 | NSMutableArray *parents; 61 | NSMutableString *buildMessage; 62 | NSString *line, *key, *val; 63 | int inMessage = 0; 64 | 65 | buildMessage = [NSMutableString new]; 66 | parents = [NSMutableArray new]; 67 | 68 | enumerator = [lines objectEnumerator]; 69 | while ((line = [enumerator nextObject]) != nil) { 70 | // NSLog(@"line: %@", line); 71 | if(!inMessage) { 72 | if([line length] == 0) { 73 | inMessage = 1; 74 | } else { 75 | NSArray *values = [line componentsSeparatedByString:@" "]; 76 | key = [values objectAtIndex: 0]; 77 | val = [values objectAtIndex: 1]; 78 | if([key isEqualToString: @"tree"]) { 79 | self.treeSha = val; 80 | } else if ([key isEqualToString: @"parent"]) { 81 | [parents addObject: val]; 82 | } else if ([key isEqualToString: @"author"]) { 83 | NSArray *name_email_date = [self parseAuthorString:line withType:@"author "]; 84 | self.author = [name_email_date objectAtIndex: 0]; 85 | self.author_email = [name_email_date objectAtIndex: 1]; 86 | self.authored_date = [name_email_date objectAtIndex: 2]; 87 | } else if ([key isEqualToString: @"committer"]) { 88 | NSArray *name_email_date = [self parseAuthorString:line withType:@"committer "]; 89 | self.committer = [name_email_date objectAtIndex: 0]; 90 | self.committer_email = [name_email_date objectAtIndex: 1]; 91 | self.committed_date = [name_email_date objectAtIndex: 2]; 92 | } 93 | } 94 | } else { 95 | [buildMessage appendString: line]; 96 | [buildMessage appendString: @"\n"]; 97 | } 98 | } 99 | self.message = buildMessage; 100 | self.parentShas = parents; 101 | } 102 | 103 | - (NSArray *) parseAuthorString:(NSString *)authorString withType:(NSString *)typeString 104 | { 105 | NSArray *name_email_date; 106 | name_email_date = [authorString componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; 107 | 108 | NSString *nameVal = [name_email_date objectAtIndex: 0]; 109 | NSString *emailVal = [name_email_date objectAtIndex: 1]; 110 | NSString *dateVal = [name_email_date objectAtIndex: 2]; 111 | NSDate *dateDateVal; 112 | dateDateVal = [NSDate dateWithTimeIntervalSince1970:[dateVal doubleValue]]; 113 | 114 | NSMutableString *tempValue = [[NSMutableString alloc] init]; 115 | [tempValue setString:nameVal]; 116 | [tempValue replaceOccurrencesOfString: typeString 117 | withString: @"" 118 | options: 0 119 | range: NSMakeRange(0, [tempValue length])]; 120 | 121 | return [NSArray arrayWithObjects:tempValue, emailVal, dateDateVal, nil]; 122 | } 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /Git/ObjGitObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitObject.h 3 | // ObjGit 4 | // 5 | 6 | #import 7 | 8 | @interface ObjGitObject : NSObject { 9 | NSString* sha; 10 | NSInteger size; 11 | NSString* type; 12 | NSString* contents; 13 | char* rawContents; 14 | int rawContentLen; 15 | NSData* raw; 16 | } 17 | 18 | @property(copy, readwrite) NSString *sha; 19 | @property(assign, readwrite) NSInteger size; 20 | @property(copy, readwrite) NSString *type; 21 | @property(copy, readwrite) NSString *contents; 22 | @property(assign, readwrite) char *rawContents; 23 | @property(assign, readwrite) int rawContentLen; 24 | @property(copy, readwrite) NSData *raw; 25 | 26 | - (id) initFromRaw:(NSData *)rawData withSha:(NSString *)shaValue; 27 | - (void) parseRaw; 28 | - (NSData *) inflateRaw:(NSData *)rawData; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Git/ObjGitObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitObject.m 3 | // ObjGit 4 | // 5 | 6 | #import "ObjGitObject.h" 7 | #import "NSData+Compression.h" 8 | 9 | @implementation ObjGitObject 10 | 11 | @synthesize sha; 12 | @synthesize size; 13 | @synthesize type; 14 | @synthesize contents; 15 | @synthesize raw; 16 | @synthesize rawContents; 17 | @synthesize rawContentLen; 18 | 19 | - (id) initFromRaw:(NSData *)rawData withSha:(NSString *)shaValue 20 | { 21 | self = [super init]; 22 | sha = shaValue; 23 | raw = [self inflateRaw:rawData]; 24 | // NSLog(@"init sha: %@", sha); 25 | // NSLog(@"raw: %@", raw); 26 | [self parseRaw]; 27 | return self; 28 | } 29 | 30 | - (void) parseRaw 31 | { 32 | char *ptr, *bytes = (char *)[raw bytes]; 33 | int len, rest; 34 | len = (ptr = memchr(bytes, nil, len = [raw length])) ? ptr - bytes : len; 35 | rest = [raw length] - len - 1; 36 | 37 | ptr++; 38 | NSString *header = [NSString stringWithCString:bytes length:len]; 39 | contents = [NSString stringWithCString:ptr length:rest]; 40 | 41 | rawContents = malloc(rest); 42 | memcpy(rawContents, ptr, rest); 43 | rawContentLen = rest; 44 | 45 | NSArray *headerData = [header componentsSeparatedByString:@" "]; 46 | 47 | type = [headerData objectAtIndex:0]; 48 | size = [[headerData objectAtIndex:1] intValue]; 49 | } 50 | 51 | - (NSData *) inflateRaw:(NSData *)rawData 52 | { 53 | return [rawData decompressedData]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Git/ObjGitServerHandler.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitServerHandler.h 3 | // ObjGit 4 | // 5 | 6 | #import 7 | #include 8 | #import "ObjGitObject.h" 9 | 10 | @interface ObjGitServerHandler : NSObject { 11 | NSInputStream* inStream; 12 | NSOutputStream* outStream; 13 | ObjGit* gitRepo; 14 | NSString* gitPath; 15 | 16 | NSMutableArray* refsRead; 17 | NSMutableArray* needRefs; 18 | NSMutableDictionary* refDict; 19 | 20 | int capabilitiesSent; 21 | } 22 | 23 | @property(assign, readwrite) NSInputStream *inStream; 24 | @property(assign, readwrite) NSOutputStream *outStream; 25 | @property(assign, readwrite) ObjGit *gitRepo; 26 | @property(assign, readwrite) NSString *gitPath; 27 | 28 | @property(assign, readwrite) NSMutableArray *refsRead; 29 | @property(assign, readwrite) NSMutableArray *needRefs; 30 | @property(assign, readwrite) NSMutableDictionary *refDict; 31 | 32 | @property(assign, readwrite) int capabilitiesSent; 33 | 34 | - (void) initWithGit:(ObjGit *)git gitPath:(NSString *)gitRepoPath input:(NSInputStream *)streamIn output:(NSOutputStream *)streamOut; 35 | - (void) handleRequest; 36 | 37 | - (void) uploadPack:(NSString *)repositoryName; 38 | - (void) receiveNeeds; 39 | - (void) uploadPackFile; 40 | - (void) sendNack; 41 | - (void) sendPackData; 42 | 43 | - (void) receivePack:(NSString *)repositoryName; 44 | - (void) gatherObjectShasFromCommit:(NSString *)shaValue; 45 | - (void) gatherObjectShasFromTree:(NSString *)shaValue; 46 | - (void) respondPack:(uint8_t *)buffer length:(int)size checkSum:(CC_SHA1_CTX *)checksum; 47 | 48 | - (void) sendRefs; 49 | - (void) sendRef:(NSString *)refName sha:(NSString *)shaString; 50 | - (void) readRefs; 51 | - (void) readPack; 52 | - (void) writeRefs; 53 | - (NSData *) readData:(int)size; 54 | - (NSString *) typeString:(int)type; 55 | - (int) typeInt:(NSString *)type; 56 | - (void) unpackDeltified:(int)type size:(int)size; 57 | 58 | - (NSData *) patchDelta:(NSData *)deltaData withObject:(ObjGitObject *)gitObject; 59 | - (NSArray *) patchDeltaHeaderSize:(NSData *)deltaData position:(unsigned long)position; 60 | 61 | - (NSString *)readServerSha; 62 | - (int) readPackHeader; 63 | - (void) unpackObject; 64 | 65 | - (void) longVal:(uint32_t)raw toByteBuffer:(uint8_t *)buffer; 66 | - (void) packetFlush; 67 | - (void) writeServer:(NSString *)dataWrite; 68 | - (void) writeServerLength:(unsigned int)length; 69 | - (void) sendPacket:(NSString *)dataSend; 70 | - (NSString *) packetReadLine; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /Git/ObjGitTest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitTest.h 3 | // ObjGit 4 | // 5 | 6 | #import 7 | 8 | @interface ObjGitTest : SenTestCase { 9 | 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Git/ObjGitTest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitTest.m 3 | // ObjGit 4 | // 5 | 6 | #import 7 | 8 | @interface ObjGitTest : SenTestCase { } 9 | @end 10 | 11 | @implementation ObjGitTest 12 | 13 | - (void) testSomething { 14 | STAssertNotNil(@"hi", @"something cool"); 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Git/ObjGitTree.h: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitTree.h 3 | // ObjGit 4 | // 5 | 6 | #import 7 | #import "ObjGitObject.h" 8 | 9 | @interface ObjGitTree : NSObject { 10 | NSArray *treeEntries; 11 | ObjGitObject *gitObject; 12 | } 13 | 14 | @property(copy, readwrite) NSArray *treeEntries; 15 | @property(assign, readwrite) ObjGitObject *gitObject; 16 | 17 | - (id) initFromGitObject:(ObjGitObject *)object; 18 | - (void) parseContent; 19 | - (void) logObject; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Git/ObjGitTree.m: -------------------------------------------------------------------------------- 1 | // 2 | // ObjGitTree.m 3 | // ObjGit 4 | // 5 | 6 | #import "ObjGit.h" 7 | #import "ObjGitObject.h" 8 | #import "ObjGitTree.h" 9 | 10 | @implementation ObjGitTree 11 | 12 | @synthesize treeEntries; 13 | @synthesize gitObject; 14 | 15 | - (id) initFromGitObject:(ObjGitObject *)object { 16 | self = [super init]; 17 | self.gitObject = object; 18 | [self parseContent]; 19 | return self; 20 | } 21 | 22 | - (void) logObject 23 | { 24 | NSLog(@"entries : %@", treeEntries); 25 | } 26 | 27 | // 100644 testfile\0[20 char sha] 28 | - (void) parseContent 29 | { 30 | char *contents = [self.gitObject rawContents]; 31 | 32 | char mode[9]; 33 | int modePtr = 0; 34 | char name[255]; 35 | int namePtr = 0; 36 | char sha[41]; 37 | unsigned char rawsha[20]; 38 | 39 | NSString *shaStr, *modeStr, *nameStr; 40 | NSArray *entry; 41 | NSMutableArray *entries; 42 | entries = [[NSMutableArray alloc] init]; 43 | 44 | int i, j, state; 45 | state = 1; 46 | 47 | for(i = 0; i < [self.gitObject rawContentLen] - 1; i++) { 48 | if(contents[i] == 0) { 49 | state = 1; 50 | for(j = 0; j < 20; j++) 51 | rawsha[j] = contents[i + j + 1]; 52 | i += 20; 53 | [ObjGit gitUnpackHex:rawsha fillSha:sha]; 54 | 55 | mode[modePtr] = 0; 56 | name[namePtr] = 0; 57 | 58 | shaStr = [[NSString alloc] initWithBytes:sha length:40 encoding:NSASCIIStringEncoding]; 59 | modeStr = [[NSString alloc] initWithBytes:mode length:modePtr encoding:NSASCIIStringEncoding]; 60 | nameStr = [[NSString alloc] initWithBytes:name length:namePtr encoding:NSUTF8StringEncoding]; 61 | 62 | entry = [NSArray arrayWithObjects:modeStr, nameStr, shaStr, nil]; 63 | [entries addObject:entry]; 64 | 65 | modePtr = 0; 66 | namePtr = 0; 67 | } else { // contents 68 | if(contents[i] == 32) { 69 | state = 2; 70 | } else if(state == 1) { // mode 71 | mode[modePtr] = contents[i]; 72 | modePtr++; 73 | } else { // name 74 | name[namePtr] = contents[i]; 75 | namePtr++; 76 | } 77 | } 78 | } 79 | treeEntries = entries; 80 | } 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /Git/runTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // runTests.m 3 | // iGitHub 4 | // 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | NSLog(@"sup"); 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Http/DDData.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface NSData (DDData) 4 | 5 | - (NSData *)md5Digest; 6 | 7 | - (NSData *)sha1Digest; 8 | 9 | - (NSString *)hexStringValue; 10 | 11 | - (NSString *)base64Encoded; 12 | - (NSData *)base64Decoded; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Http/DDNumber.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum; 7 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum; 8 | 9 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum; 10 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum; 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /Http/DDNumber.m: -------------------------------------------------------------------------------- 1 | #import "DDNumber.h" 2 | 3 | 4 | @implementation NSNumber (DDNumber) 5 | 6 | + (BOOL)parseString:(NSString *)str intoSInt64:(SInt64 *)pNum 7 | { 8 | errno = 0; 9 | 10 | #if __LP64__ 11 | // long = 64 bit 12 | *pNum = strtol([str UTF8String], NULL, 10); 13 | #else 14 | // long = 32 bit 15 | // long long = 64 bit 16 | *pNum = strtoll([str UTF8String], NULL, 10); 17 | #endif 18 | 19 | if(errno != 0) 20 | return NO; 21 | else 22 | return YES; 23 | } 24 | 25 | + (BOOL)parseString:(NSString *)str intoUInt64:(UInt64 *)pNum 26 | { 27 | errno = 0; 28 | 29 | #if __LP64__ 30 | // unsigned long = 64 bit 31 | *pNum = strtoul([str UTF8String], NULL, 10); 32 | #else 33 | // unsigned long = 32 bit 34 | // unsigned long long = 64 bit 35 | *pNum = strtoull([str UTF8String], NULL, 10); 36 | #endif 37 | 38 | if(errno != 0) 39 | return NO; 40 | else 41 | return YES; 42 | } 43 | 44 | + (BOOL)parseString:(NSString *)str intoNSInteger:(NSInteger *)pNum 45 | { 46 | errno = 0; 47 | 48 | // On LP64, NSInteger = long = 64 bit 49 | // Otherwise, NSInteger = int = long = 32 bit 50 | 51 | *pNum = strtol([str UTF8String], NULL, 10); 52 | 53 | if(errno != 0) 54 | return NO; 55 | else 56 | return YES; 57 | } 58 | 59 | + (BOOL)parseString:(NSString *)str intoNSUInteger:(NSUInteger *)pNum 60 | { 61 | errno = 0; 62 | 63 | // On LP64, NSUInteger = unsigned long = 64 bit 64 | // Otherwise, NSUInteger = unsigned int = unsigned long = 32 bit 65 | 66 | *pNum = strtoul([str UTF8String], NULL, 10); 67 | 68 | if(errno != 0) 69 | return NO; 70 | else 71 | return YES; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Http/DDRange.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DDRange is the functional equivalent of a 64 bit NSRange. 3 | * The HTTP Server is designed to support very large files. 4 | * On 32 bit architectures (ppc, i386) NSRange uses unsigned 32 bit integers. 5 | * This only supports a range of up to 4 gigabytes. 6 | * By defining our own variant, we can support a range up to 16 exabytes. 7 | * 8 | * All effort is given such that DDRange functions EXACTLY the same as NSRange. 9 | **/ 10 | 11 | #import 12 | #import 13 | 14 | @class NSString; 15 | 16 | typedef struct _DDRange { 17 | UInt64 location; 18 | UInt64 length; 19 | } DDRange; 20 | 21 | typedef DDRange *DDRangePointer; 22 | 23 | NS_INLINE DDRange DDMakeRange(UInt64 loc, UInt64 len) { 24 | DDRange r; 25 | r.location = loc; 26 | r.length = len; 27 | return r; 28 | } 29 | 30 | NS_INLINE UInt64 DDMaxRange(DDRange range) { 31 | return (range.location + range.length); 32 | } 33 | 34 | NS_INLINE BOOL DDLocationInRange(UInt64 loc, DDRange range) { 35 | return (loc - range.location < range.length); 36 | } 37 | 38 | NS_INLINE BOOL DDEqualRanges(DDRange range1, DDRange range2) { 39 | return ((range1.location == range2.location) && (range1.length == range2.length)); 40 | } 41 | 42 | FOUNDATION_EXPORT DDRange DDUnionRange(DDRange range1, DDRange range2); 43 | FOUNDATION_EXPORT DDRange DDIntersectionRange(DDRange range1, DDRange range2); 44 | FOUNDATION_EXPORT NSString *DDStringFromRange(DDRange range); 45 | FOUNDATION_EXPORT DDRange DDRangeFromString(NSString *aString); 46 | 47 | @interface NSValue (NSValueDDRangeExtensions) 48 | 49 | + (NSValue *)valueWithDDRange:(DDRange)range; 50 | - (DDRange)ddrangeValue; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Http/DDRange.m: -------------------------------------------------------------------------------- 1 | #import "DDRange.h" 2 | #import "DDNumber.h" 3 | 4 | DDRange DDUnionRange(DDRange range1, DDRange range2) 5 | { 6 | DDRange result; 7 | 8 | result.location = MIN(range1.location, range2.location); 9 | result.length = MAX(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 10 | 11 | return result; 12 | } 13 | 14 | DDRange DDIntersectionRange(DDRange range1, DDRange range2) 15 | { 16 | DDRange result; 17 | 18 | if((DDMaxRange(range1) < range2.location) || (DDMaxRange(range2) < range1.location)) 19 | { 20 | return DDMakeRange(0, 0); 21 | } 22 | 23 | result.location = MAX(range1.location, range2.location); 24 | result.length = MIN(DDMaxRange(range1), DDMaxRange(range2)) - result.location; 25 | 26 | return result; 27 | } 28 | 29 | NSString *DDStringFromRange(DDRange range) 30 | { 31 | return [NSString stringWithFormat:@"{%qu, %qu}", range.location, range.length]; 32 | } 33 | 34 | DDRange DDRangeFromString(NSString *aString) 35 | { 36 | DDRange result = DDMakeRange(0, 0); 37 | 38 | // NSRange will ignore '-' characters, but not '+' characters 39 | NSCharacterSet *cset = [NSCharacterSet characterSetWithCharactersInString:@"+0123456789"]; 40 | 41 | NSScanner *scanner = [NSScanner scannerWithString:aString]; 42 | [scanner setCharactersToBeSkipped:[cset invertedSet]]; 43 | 44 | NSString *str1 = nil; 45 | NSString *str2 = nil; 46 | 47 | BOOL found1 = [scanner scanCharactersFromSet:cset intoString:&str1]; 48 | BOOL found2 = [scanner scanCharactersFromSet:cset intoString:&str2]; 49 | 50 | if(found1) [NSNumber parseString:str1 intoUInt64:&result.location]; 51 | if(found2) [NSNumber parseString:str2 intoUInt64:&result.length]; 52 | 53 | return result; 54 | } 55 | 56 | @implementation NSValue (NSValueDDRangeExtensions) 57 | 58 | + (NSValue *)valueWithDDRange:(DDRange)range 59 | { 60 | return [NSValue valueWithBytes:&range objCType:@encode(DDRange)]; 61 | } 62 | 63 | - (DDRange)ddrangeValue 64 | { 65 | DDRange result; 66 | [self getValue:&result]; 67 | return result; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /Http/HTTPAuthenticationRequest.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if TARGET_OS_IPHONE 4 | // Note: You may need to add the CFNetwork Framework to your project 5 | #import 6 | #endif 7 | 8 | 9 | @interface HTTPAuthenticationRequest : NSObject 10 | { 11 | BOOL isBasic; 12 | BOOL isDigest; 13 | 14 | NSString *base64Credentials; 15 | 16 | NSString *username; 17 | NSString *realm; 18 | NSString *nonce; 19 | NSString *uri; 20 | NSString *qop; 21 | NSString *nc; 22 | NSString *cnonce; 23 | NSString *response; 24 | } 25 | - (id)initWithRequest:(CFHTTPMessageRef)request; 26 | 27 | - (BOOL)isBasic; 28 | - (BOOL)isDigest; 29 | 30 | // Basic 31 | - (NSString *)base64Credentials; 32 | 33 | // Digest 34 | - (NSString *)username; 35 | - (NSString *)realm; 36 | - (NSString *)nonce; 37 | - (NSString *)uri; 38 | - (NSString *)qop; 39 | - (NSString *)nc; 40 | - (NSString *)cnonce; 41 | - (NSString *)response; 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Http/HTTPConnection.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #if TARGET_OS_IPHONE 4 | // Note: You may need to add the CFNetwork Framework to your project 5 | #import 6 | #endif 7 | 8 | @class AsyncSocket; 9 | @class HTTPServer; 10 | @protocol HTTPResponse; 11 | 12 | 13 | #define HTTPConnectionDidDieNotification @"HTTPConnectionDidDie" 14 | 15 | @interface HTTPConnection : NSObject 16 | { 17 | AsyncSocket *asyncSocket; 18 | HTTPServer *server; 19 | 20 | CFHTTPMessageRef request; 21 | int numHeaderLines; 22 | 23 | NSString *nonce; 24 | long lastNC; 25 | 26 | NSObject *httpResponse; 27 | 28 | NSMutableArray *ranges; 29 | NSMutableArray *ranges_headers; 30 | NSString *ranges_boundry; 31 | int rangeIndex; 32 | 33 | UInt64 requestContentLength; 34 | UInt64 requestContentLengthReceived; 35 | } 36 | 37 | - (id)initWithAsyncSocket:(AsyncSocket *)newSocket forServer:(HTTPServer *)myServer; 38 | 39 | - (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path; 40 | 41 | - (BOOL)isSecureServer; 42 | - (NSArray *)sslIdentityAndCertificates; 43 | 44 | - (BOOL)isPasswordProtected:(NSString *)path; 45 | - (BOOL)useDigestAccessAuthentication; 46 | - (NSString *)realm; 47 | - (NSString *)passwordForUser:(NSString *)username; 48 | 49 | - (NSString *)filePathForURI:(NSString *)path; 50 | 51 | - (NSObject *)httpResponseForMethod:(NSString *)method URI:(NSString *)path; 52 | 53 | - (void)prepareForBodyWithSize:(UInt64)contentLength; 54 | - (void)processDataChunk:(NSData *)postDataChunk; 55 | 56 | - (void)handleVersionNotSupported:(NSString *)version; 57 | - (void)handleAuthenticationFailed; 58 | - (void)handleResourceNotFound; 59 | - (void)handleInvalidRequest:(NSData *)data; 60 | - (void)handleUnknownMethod:(NSString *)method; 61 | 62 | - (NSData *)preprocessResponse:(CFHTTPMessageRef)response; 63 | - (NSData *)preprocessErrorResponse:(CFHTTPMessageRef)response; 64 | 65 | - (void)die; 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /Http/HTTPResponse.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @protocol HTTPResponse 5 | 6 | - (UInt64)contentLength; 7 | 8 | - (UInt64)offset; 9 | - (void)setOffset:(UInt64)offset; 10 | 11 | - (NSData *)readDataOfLength:(unsigned int)length; 12 | 13 | #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 14 | 15 | @optional 16 | - (NSDictionary *)httpHeaders; 17 | 18 | #endif 19 | 20 | @end 21 | 22 | @interface HTTPFileResponse : NSObject 23 | { 24 | NSString *filePath; 25 | NSFileHandle *fileHandle; 26 | } 27 | 28 | - (id)initWithFilePath:(NSString *)filePath; 29 | - (NSString *)filePath; 30 | 31 | @end 32 | 33 | @interface HTTPDataResponse : NSObject 34 | { 35 | unsigned offset; 36 | NSData *data; 37 | } 38 | 39 | - (id)initWithData:(NSData *)data; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Http/HTTPResponse.m: -------------------------------------------------------------------------------- 1 | #import "HTTPResponse.h" 2 | 3 | 4 | @implementation HTTPFileResponse 5 | 6 | - (id)initWithFilePath:(NSString *)filePathParam 7 | { 8 | if(self = [super init]) 9 | { 10 | filePath = [filePathParam copy]; 11 | fileHandle = [[NSFileHandle fileHandleForReadingAtPath:filePath] retain]; 12 | } 13 | return self; 14 | } 15 | 16 | - (void)dealloc 17 | { 18 | [filePath release]; 19 | [fileHandle closeFile]; 20 | [fileHandle release]; 21 | [super dealloc]; 22 | } 23 | 24 | - (UInt64)contentLength 25 | { 26 | NSDictionary *fileAttributes = [[NSFileManager defaultManager] fileAttributesAtPath:filePath traverseLink:NO]; 27 | 28 | NSNumber *fileSize = [fileAttributes objectForKey:NSFileSize]; 29 | 30 | return (UInt64)[fileSize unsignedLongLongValue]; 31 | } 32 | 33 | - (UInt64)offset 34 | { 35 | return (UInt64)[fileHandle offsetInFile]; 36 | } 37 | 38 | - (void)setOffset:(UInt64)offset 39 | { 40 | [fileHandle seekToFileOffset:offset]; 41 | } 42 | 43 | - (NSData *)readDataOfLength:(unsigned int)length 44 | { 45 | return [fileHandle readDataOfLength:length]; 46 | } 47 | 48 | - (NSString *)filePath 49 | { 50 | return filePath; 51 | } 52 | 53 | @end 54 | 55 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | #pragma mark - 57 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 58 | 59 | @implementation HTTPDataResponse 60 | 61 | - (id)initWithData:(NSData *)dataParam 62 | { 63 | if(self = [super init]) 64 | { 65 | offset = 0; 66 | data = [dataParam retain]; 67 | } 68 | return self; 69 | } 70 | 71 | - (void)dealloc 72 | { 73 | [data release]; 74 | [super dealloc]; 75 | } 76 | 77 | - (UInt64)contentLength 78 | { 79 | return (UInt64)[data length]; 80 | } 81 | 82 | - (UInt64)offset 83 | { 84 | return offset; 85 | } 86 | 87 | - (void)setOffset:(UInt64)offsetParam 88 | { 89 | offset = offsetParam; 90 | } 91 | 92 | - (NSData *)readDataOfLength:(unsigned int)lengthParameter 93 | { 94 | unsigned int remaining = [data length] - offset; 95 | unsigned int length = lengthParameter < remaining ? lengthParameter : remaining; 96 | 97 | void *bytes = (void *)([data bytes] + offset); 98 | 99 | offset += length; 100 | 101 | return [NSData dataWithBytesNoCopy:bytes length:length freeWhenDone:NO]; 102 | } 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /Http/HTTPServer.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @class AsyncSocket; 4 | 5 | 6 | @interface HTTPServer : NSObject 7 | { 8 | // Underlying asynchronous TCP/IP socket 9 | AsyncSocket *asyncSocket; 10 | 11 | // Standard delegate 12 | id delegate; 13 | 14 | // HTTP server configuration 15 | NSURL *documentRoot; 16 | Class connectionClass; 17 | 18 | // NSNetService and related variables 19 | NSNetService *netService; 20 | NSString *domain; 21 | NSString *type; 22 | NSString *name; 23 | UInt16 port; 24 | NSDictionary *txtRecordDictionary; 25 | 26 | NSMutableArray *connections; 27 | } 28 | 29 | - (id)delegate; 30 | - (void)setDelegate:(id)newDelegate; 31 | 32 | - (NSURL *)documentRoot; 33 | - (void)setDocumentRoot:(NSURL *)value; 34 | 35 | - (Class)connectionClass; 36 | - (void)setConnectionClass:(Class)value; 37 | 38 | - (NSString *)domain; 39 | - (void)setDomain:(NSString *)value; 40 | 41 | - (NSString *)type; 42 | - (void)setType:(NSString *)value; 43 | 44 | - (NSString *)name; 45 | - (NSString *)publishedName; 46 | - (void)setName:(NSString *)value; 47 | 48 | - (UInt16)port; 49 | - (void)setPort:(UInt16)value; 50 | 51 | - (NSDictionary *)TXTRecordDictionary; 52 | - (void)setTXTRecordDictionary:(NSDictionary *)dict; 53 | 54 | - (BOOL)start:(NSError **)error; 55 | - (BOOL)stop; 56 | 57 | - (uint)numberOfHTTPConnections; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | icon.png 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundlePackageType 18 | APPL 19 | CFBundleVersion 20 | 1.0 21 | UIRequiresPersistentWiFi 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (The MIT License) 2 | 3 | Copyright (c) 2008 Scott Chacon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | 'Software'), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Prefix.pch: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: Prefix.pch 4 | Abstract: This file is included for support purposes and isn't necessary for 5 | understanding this sample. 6 | 7 | Version: 1.0 8 | 9 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 10 | ("Apple") in consideration of your agreement to the following terms, and your 11 | use, installation, modification or redistribution of this Apple software 12 | constitutes acceptance of these terms. If you do not agree with these terms, 13 | please do not use, install, modify or redistribute this Apple software. 14 | 15 | In consideration of your agreement to abide by the following terms, and subject 16 | to these terms, Apple grants you a personal, non-exclusive license, under 17 | Apple's copyrights in this original Apple software (the "Apple Software"), to 18 | use, reproduce, modify and redistribute the Apple Software, with or without 19 | modifications, in source and/or binary forms; provided that if you redistribute 20 | the Apple Software in its entirety and without modifications, you must retain 21 | this notice and the following text and disclaimers in all such redistributions 22 | of the Apple Software. 23 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 24 | to endorse or promote products derived from the Apple Software without specific 25 | prior written permission from Apple. Except as expressly stated in this notice, 26 | no other rights or licenses, express or implied, are granted by Apple herein, 27 | including but not limited to any patent rights that may be infringed by your 28 | derivative works or by other works in which the Apple Software may be 29 | incorporated. 30 | 31 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 32 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 33 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 35 | COMBINATION WITH YOUR PRODUCTS. 36 | 37 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 38 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 39 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 40 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 41 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 42 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 43 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | 45 | Copyright (C) 2008 Apple Inc. All Rights Reserved. 46 | 47 | */ 48 | 49 | #ifdef __OBJC__ 50 | #import 51 | #endif 52 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | Main Features / TODO 2 | ==================================== 3 | 4 | * integrate CocoaGit, replacing ObjGit 5 | - add server functionality to CocoaGit 6 | 7 | * push / pull works locally and over bonjour 8 | 9 | * browse local repos 10 | 11 | * uses file handles for writing / reading packs instead of memory 12 | - library option? 13 | 14 | 15 | 16 | Cloning List 17 | ==================================== 18 | 19 | * http smart server 20 | - push 21 | - info/refs 22 | - dumb [SHA ref, etc] 23 | - smart 24 | C: GET $GIT_URL/info/refs?service=git-upload-pack HTTP/1.0 25 | S: 200 OK 26 | S: Content-Type: application/x-git-upload-pack-advertisement 27 | S: Cache-Control: no-cache 28 | S: 29 | S: ....# service=git-upload-pack 30 | S: ....95dcfa3633004da0049d3d0fa03f80589cbcaf31 refs/heads/maint\0 multi_ack 31 | S: ....d049f6c27a2244e12041955e262a404c7faba355 refs/heads/master 32 | S: ....2cb58b79488a98d2721cea644875a8dd0026b115 refs/tags/v1.0 33 | S: ....a3c2e2402b99163d1d59756e5f207ae21cccba4c refs/tags/v1.0^{} 34 | C: POST $GIT_URL/git-receive-pack HTTP/1.0 35 | C: ....0a53e9ddeaddad63ad106860237bbf53411d11a7 441b40d833fdfa93eb2908e52742248faf0ee993 refs/heads/maint\0 report-status 36 | C: 0000 37 | C: PACK.... 38 | 39 | 40 | - fetch 41 | - 42 | 43 | * http smart client 44 | 45 | * Bonjour announcement 46 | 47 | 48 | ToDo List 49 | ==================================== 50 | 51 | * flick up/down to browse commits 52 | 53 | * status bar (when clones/fetches are happening) 54 | 55 | * about page - who did this 56 | 57 | * how to page 58 | 59 | * delete a repo 60 | 61 | * public / private repos 62 | 63 | * commit key for private repos 64 | 65 | * ipad version 66 | 67 | * bonjour sniffing - clone from other iphones 68 | 69 | 70 | GitHub Features 71 | ==================================== 72 | 73 | * github user/pass login 74 | 75 | * a "search github" feature 76 | 77 | * fork/clone a github project 78 | 79 | * send a pull request 80 | 81 | * add a list of remotes of people that forked you 82 | 83 | 84 | 85 | Implementation Get-Back-Tos 86 | ==================================== 87 | 88 | * read/write blob data from disk rather than memory to handle objects > 100M 89 | 90 | * won't handle multi-depth refs 'chacon/master', etc 91 | 92 | * doesn't handle ofs-deltas, but the client shouldn't be sending them 93 | 94 | * doesn't keep objects in packs 95 | -------------------------------------------------------------------------------- /assets/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/Default.png -------------------------------------------------------------------------------- /assets/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/bg.png -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/icon.png -------------------------------------------------------------------------------- /assets/octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/octocat.png -------------------------------------------------------------------------------- /assets/rssicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/rssicon.png -------------------------------------------------------------------------------- /assets/server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/server.png -------------------------------------------------------------------------------- /assets/servericon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/servericon.png -------------------------------------------------------------------------------- /assets/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/schacon/igithub/417071e63b99d182f1840ba9fde98164dcf1e9d3/assets/test.png -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | */ 4 | 5 | #import 6 | #import "Git.h" 7 | 8 | int main(int argc, char *argv[]) 9 | { 10 | NSAutoreleasePool* pool = [NSAutoreleasePool new]; 11 | 12 | UIApplicationMain(argc, argv, nil, @"AppController"); 13 | 14 | [pool release]; 15 | 16 | return 0; 17 | } 18 | --------------------------------------------------------------------------------