mirror of
https://github.com/kennethreitz-archive/gitx.git
synced 2026-06-05 23:40:18 +00:00
Add a GitX:// protocol handler
This allows to read in arbitrary blobs from the repository. For more information, see the CallingFromWebKit.txt document in the Documentation/ directory.
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#import "PBRepositoryDocumentController.h"
|
||||
#import "PBCLIProxy.h"
|
||||
#import "PBServicesController.h"
|
||||
#import "PBGitXProtocol.h"
|
||||
|
||||
@implementation ApplicationController
|
||||
@synthesize cliProxy;
|
||||
@@ -34,6 +35,9 @@
|
||||
|
||||
- (void)registerServices
|
||||
{
|
||||
// Register URL
|
||||
[NSURLProtocol registerClass:[PBGitXProtocol class]];
|
||||
|
||||
// Register the service class
|
||||
PBServicesController *services = [[PBServicesController alloc] init];
|
||||
[NSApp setServicesProvider:services];
|
||||
|
||||
@@ -78,4 +78,24 @@ async, which means that it doesn't matter if it takes a long time to run.
|
||||
|
||||
While you can have direct access to most objects, sometimes it is useful to
|
||||
have an async task, for example if the operation can take a long time. Use
|
||||
this function to keep the UI responsive.
|
||||
this function to keep the UI responsive.
|
||||
|
||||
Loading files from WebKit
|
||||
=========================
|
||||
|
||||
All views that have a subclass of PBWebController set as ResourceLoadDelegate
|
||||
(this happens automatically if you assign a view to your controllers) gain
|
||||
access to the GitX:// protocol. This protocol allows you to load in blobs from
|
||||
the repository. The format is as follows:
|
||||
|
||||
GitX://REVISION/path/to/file
|
||||
|
||||
Which means that revision can't have a path separator in it (so HEAD is valid,
|
||||
but pu/pb/fix_it is not). You also can't just pass on a blob oid. These things
|
||||
will probably be fixed in future revisions of the protocol.
|
||||
|
||||
What this allows you to do, for instance, is to display images that have
|
||||
changed. For example, if you want to show the new file from a diff, you can
|
||||
use something like
|
||||
|
||||
<img src="GitX://HEAD:Images/new_file.png">
|
||||
@@ -68,6 +68,7 @@
|
||||
F5E92A1B0E88550E00056E75 /* empty_file.png in Resources */ = {isa = PBXBuildFile; fileRef = F5E92A1A0E88550E00056E75 /* empty_file.png */; };
|
||||
F5E92A230E88569500056E75 /* new_file.png in Resources */ = {isa = PBXBuildFile; fileRef = F5E92A220E88569500056E75 /* new_file.png */; };
|
||||
F5EF8C8E0E9D4A5D0050906B /* PBWebController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5EF8C8D0E9D4A5D0050906B /* PBWebController.m */; };
|
||||
F5FC41F40EBCBD4300191D80 /* PBGitXProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC41F30EBCBD4300191D80 /* PBGitXProtocol.m */; };
|
||||
F5FE6C030EB13BC900F30D12 /* PBServicesController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FE6C020EB13BC900F30D12 /* PBServicesController.m */; };
|
||||
F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; };
|
||||
F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E790E082E440006317A /* PBGitGrapher.m */; };
|
||||
@@ -199,6 +200,8 @@
|
||||
F5E92A220E88569500056E75 /* new_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = new_file.png; path = Images/new_file.png; sourceTree = "<group>"; };
|
||||
F5EF8C8C0E9D4A5D0050906B /* PBWebController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBWebController.h; sourceTree = "<group>"; };
|
||||
F5EF8C8D0E9D4A5D0050906B /* PBWebController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBWebController.m; sourceTree = "<group>"; };
|
||||
F5FC41F20EBCBD4300191D80 /* PBGitXProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitXProtocol.h; sourceTree = "<group>"; };
|
||||
F5FC41F30EBCBD4300191D80 /* PBGitXProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitXProtocol.m; sourceTree = "<group>"; };
|
||||
F5FE6C010EB13BC900F30D12 /* PBServicesController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBServicesController.h; sourceTree = "<group>"; };
|
||||
F5FE6C020EB13BC900F30D12 /* PBServicesController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBServicesController.m; sourceTree = "<group>"; };
|
||||
F5FF4E160E0829C20006317A /* PBGitRevList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevList.h; sourceTree = "<group>"; };
|
||||
@@ -410,6 +413,8 @@
|
||||
F56244080E9684B0002B6C44 /* PBUnsortableTableHeader.m */,
|
||||
F50A41210EBB875D00208746 /* PBNiceSplitView.h */,
|
||||
F50A41220EBB875D00208746 /* PBNiceSplitView.m */,
|
||||
F5FC41F20EBCBD4300191D80 /* PBGitXProtocol.h */,
|
||||
F5FC41F30EBCBD4300191D80 /* PBGitXProtocol.m */,
|
||||
);
|
||||
name = Aux;
|
||||
sourceTree = "<group>";
|
||||
@@ -643,6 +648,7 @@
|
||||
F5E424180EA3E4EB0046E362 /* PBWebDiffController.m in Sources */,
|
||||
F5FE6C030EB13BC900F30D12 /* PBServicesController.m in Sources */,
|
||||
F50A41230EBB875D00208746 /* PBNiceSplitView.m in Sources */,
|
||||
F5FC41F40EBCBD4300191D80 /* PBGitXProtocol.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// PBGitXProtocol.h
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 01-11-08.
|
||||
// Copyright 2008 Pieter de Bie. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#import "PBGitRepository.h"
|
||||
|
||||
@interface PBGitXProtocol : NSURLProtocol {
|
||||
NSFileHandle *handle;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface NSURLRequest (PBGitXProtocol)
|
||||
@property (readonly) PBGitRepository *repository;
|
||||
@end
|
||||
|
||||
@interface NSMutableURLRequest (PBGitXProtocol)
|
||||
@property (retain) PBGitRepository *repository;
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// PBGitXProtocol.m
|
||||
// GitX
|
||||
//
|
||||
// Created by Pieter de Bie on 01-11-08.
|
||||
// Copyright 2008 Pieter de Bie. All rights reserved.
|
||||
//
|
||||
|
||||
#import "PBGitXProtocol.h"
|
||||
|
||||
|
||||
@implementation PBGitXProtocol
|
||||
|
||||
+ (BOOL) canInitWithRequest:(NSURLRequest *)request
|
||||
{
|
||||
return [[[request URL] scheme] isEqualToString:@"GitX"];
|
||||
}
|
||||
|
||||
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
|
||||
{
|
||||
return request;
|
||||
}
|
||||
|
||||
-(void)startLoading
|
||||
{
|
||||
NSURL *url = [[self request] URL];
|
||||
PBGitRepository *repo = [[self request] repository];
|
||||
|
||||
if(!repo) {
|
||||
[[self client] URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:nil]];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *specifier = [NSString stringWithFormat:@"%@:%@", [url host], [[url path] substringFromIndex:1]];
|
||||
handle = [repo handleInWorkDirForArguments:[NSArray arrayWithObjects:@"cat-file", @"blob", specifier, nil]];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didFinishFileLoad:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
|
||||
[handle readToEndOfFileInBackgroundAndNotify];
|
||||
|
||||
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:[[self request] URL]
|
||||
MIMEType:nil
|
||||
expectedContentLength:-1
|
||||
textEncodingName:nil];
|
||||
|
||||
[[self client] URLProtocol:self
|
||||
didReceiveResponse:response
|
||||
cacheStoragePolicy:NSURLCacheStorageNotAllowed];
|
||||
}
|
||||
|
||||
- (void) didFinishFileLoad:(NSNotification *)notification
|
||||
{
|
||||
NSData *data = [[notification userInfo] valueForKey:NSFileHandleNotificationDataItem];
|
||||
[[self client] URLProtocol:self didLoadData:data];
|
||||
[[self client] URLProtocolDidFinishLoading:self];
|
||||
}
|
||||
|
||||
- (void) stopLoading
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSURLRequest (PBGitXProtocol)
|
||||
|
||||
- (PBGitRepository *) repository
|
||||
{
|
||||
return [NSURLProtocol propertyForKey:@"PBGitRepository" inRequest:self];
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation NSMutableURLRequest (PBGitXProtocol)
|
||||
@dynamic repository;
|
||||
|
||||
- (void) setRepository:(PBGitRepository *)repository
|
||||
{
|
||||
[NSURLProtocol setProperty:repository forKey:@"PBGitRepository" inRequest:self];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
// For async git reading
|
||||
NSMapTable *callbacks;
|
||||
|
||||
// For the repository access
|
||||
IBOutlet id repository;
|
||||
}
|
||||
|
||||
@property (retain) NSString *startFile;
|
||||
@property (retain) id repository;
|
||||
|
||||
- (WebScriptObject *) script;
|
||||
@end
|
||||
|
||||
+26
-3
@@ -8,11 +8,13 @@
|
||||
|
||||
#import "PBWebController.h"
|
||||
#import "PBGitRepository.h"
|
||||
#import "PBGitXProtocol.h"
|
||||
|
||||
#include <SystemConfiguration/SCNetworkReachability.h>
|
||||
|
||||
@implementation PBWebController
|
||||
|
||||
@synthesize startFile;
|
||||
@synthesize startFile, repository;
|
||||
|
||||
- (void) awakeFromNib
|
||||
{
|
||||
@@ -25,6 +27,7 @@
|
||||
finishedLoading = NO;
|
||||
[view setUIDelegate:self];
|
||||
[view setFrameLoadDelegate:self];
|
||||
[view setResourceLoadDelegate:self];
|
||||
[[view mainFrame] loadRequest:request];
|
||||
}
|
||||
|
||||
@@ -50,6 +53,26 @@
|
||||
NSLog(@"Error from webkit: %@", dictionary);
|
||||
}
|
||||
|
||||
- (NSURLRequest *)webView:(WebView *)sender
|
||||
resource:(id)identifier
|
||||
willSendRequest:(NSURLRequest *)request
|
||||
redirectResponse:(NSURLResponse *)redirectResponse
|
||||
fromDataSource:(WebDataSource *)dataSource
|
||||
{
|
||||
if (!self.repository)
|
||||
return request;
|
||||
|
||||
// TODO: Change this to canInitWithRequest
|
||||
if ([[[request URL] scheme] isEqualToString:@"GitX"]) {
|
||||
NSMutableURLRequest *newRequest = [request mutableCopy];
|
||||
[newRequest setRepository:self.repository];
|
||||
return newRequest;
|
||||
}
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
+ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector
|
||||
{
|
||||
return NO;
|
||||
@@ -81,7 +104,7 @@
|
||||
|
||||
#pragma mark Using async function from JS
|
||||
|
||||
- (void) runCommand:(WebScriptObject *)arguments inRepository:(PBGitRepository *)repository callBack:(WebScriptObject *)callBack
|
||||
- (void) runCommand:(WebScriptObject *)arguments inRepository:(PBGitRepository *)repo callBack:(WebScriptObject *)callBack
|
||||
{
|
||||
// The JS bridge does not handle JS Arrays, even though the docs say it does. So, we convert it ourselves.
|
||||
int length = [[arguments valueForKey:@"length"] intValue];
|
||||
@@ -90,7 +113,7 @@
|
||||
for (i = 0; i < length; i++)
|
||||
[realArguments addObject:[arguments webScriptValueAtIndex:i]];
|
||||
|
||||
NSFileHandle *handle = [repository handleInWorkDirForArguments:realArguments];
|
||||
NSFileHandle *handle = [repo handleInWorkDirForArguments:realArguments];
|
||||
[callbacks setObject:callBack forKey:handle];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(JSRunCommandDone:) name:NSFileHandleReadToEndOfFileCompletionNotification object:handle];
|
||||
[handle readToEndOfFileInBackgroundAndNotify];
|
||||
|
||||
Reference in New Issue
Block a user