diff --git a/.gitignore b/.gitignore index 94061ea70..39b909942 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ +.DS_Store build build/revision +._* *.xcodeproj/ !*.xcodeproj/project.pbxproj Nightly.app.zip diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 255017267..000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "libgit2"] - path = libgit2 - url = git://github.com/pieter/libgit2.git diff --git a/AIURLAdditions.h b/AIURLAdditions.h new file mode 100644 index 000000000..300da08ca --- /dev/null +++ b/AIURLAdditions.h @@ -0,0 +1,44 @@ +/* + * Adium is the legal property of its developers, whose names are listed in the copyright file included + * with this source distribution. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +/*! + * Provides some additional functionality when working with \c NSURL objects. + */ +@interface NSURL (AIURLAdditions) + +/** + * @brief The length of the URL. + * + * @return The length (number of characters) of the absolute URL. + */ +@property (readonly, nonatomic) NSUInteger length; + +/*! + * @brief Returns the argument for the specified key in the query string component of + * the URL. + * + * The search is case-sensitive, and the caller is responsible for removing any + * percent escapes, as well as "+" escapes, too. + * + * @param key The key whose value should be located and returned. + * @return The argument for the specified key, or \c nil if the key could not + * be found in the query string. + */ +- (NSString *)queryArgumentForKey:(NSString *)key; +- (NSString *)queryArgumentForKey:(NSString *)key withDelimiter:(NSString *)delimiter; + +@end diff --git a/AIURLAdditions.m b/AIURLAdditions.m new file mode 100644 index 000000000..2b99947cc --- /dev/null +++ b/AIURLAdditions.m @@ -0,0 +1,55 @@ +/* + * Adium is the legal property of its developers, whose names are listed in the copyright file included + * with this source distribution. + * + * This program is free software; you can redistribute it and/or modify it under the terms of the GNU + * General Public License as published by the Free Software Foundation; either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even + * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program; if not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#import "AIURLAdditions.h" + +@implementation NSURL (AIURLAdditions) + +- (NSUInteger)length +{ + return [[self absoluteString] length]; +} + +- (NSString *)queryArgumentForKey:(NSString *)key withDelimiter:(NSString *)delimiter +{ + for (NSString *obj in [[self query] componentsSeparatedByString:delimiter]) { + NSArray *keyAndValue = [obj componentsSeparatedByString:@"="]; + + if (([keyAndValue count] >= 2) && ([[keyAndValue objectAtIndex:0] caseInsensitiveCompare:key] == NSOrderedSame)) { + return [keyAndValue objectAtIndex:1]; + } + } + + return nil; +} + +- (NSString *)queryArgumentForKey:(NSString *)key +{ + NSString *delimiter; + + // The arguments in query strings can be delimited with a semicolon (';') or an ampersand ('&'). Since it's not + // likely a single URL would use both types of delimeters, we'll attempt to pick one and use it. + if ([[self query] rangeOfString:@";"].location != NSNotFound) { + delimiter = @";"; + } else { + // Assume '&' by default, since that's more common + delimiter = @"&"; + } + + return [self queryArgumentForKey:key withDelimiter:delimiter]; +} + +@end diff --git a/ApplicationController.h b/ApplicationController.h index d611acbba..a417854df 100644 --- a/ApplicationController.h +++ b/ApplicationController.h @@ -7,7 +7,6 @@ // #import -#import "PBGitRepository.h" @class PBCloneRepositoryPanel; @@ -20,6 +19,8 @@ NSManagedObjectContext *managedObjectContext; PBCloneRepositoryPanel *cloneRepositoryPanel; + + NSDictionary *notificationUserInfo; } - (NSPersistentStoreCoordinator *)persistentStoreCoordinator; diff --git a/ApplicationController.m b/ApplicationController.m index 6794b14d1..f8a5b8455 100644 --- a/ApplicationController.m +++ b/ApplicationController.m @@ -17,6 +17,13 @@ #import "PBGitDefaults.h" #import "PBCloneRepositoryPanel.h" #import "Sparkle/SUUpdater.h" +#import "AIURLAdditions.h" +#import "PBGitRepository.h" + +@interface ApplicationController () +- (void) cleanUpRemotesOnError; +@end + @implementation ApplicationController @@ -31,7 +38,7 @@ - (ApplicationController*)init if(![[NSBundle bundleWithPath:@"/System/Library/Frameworks/Quartz.framework/Frameworks/QuickLookUI.framework"] load]) if(![[NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/QuickLookUI.framework"] load]) - NSLog(@"Could not load QuickLook"); + DLog(@"Could not load QuickLook"); /* Value Transformers */ NSValueTransformer *transformer = [[PBNSURLPathUserDefaultsTransfomer alloc] init]; @@ -55,26 +62,39 @@ - (void)registerServices int serviceVersion = [[NSUserDefaults standardUserDefaults] integerForKey:@"Services Version"]; if (serviceVersion < 2) { - NSLog(@"Updating services menu…"); + DLog(@"Updating services menu…"); NSUpdateDynamicServices(); [[NSUserDefaults standardUserDefaults] setInteger:2 forKey:@"Services Version"]; } } +- (void)applicationWillFinishLaunching:(NSNotification*)notification +{ + [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self + andSelector:@selector(getUrl:withReplyEvent:) + forEventClass:kInternetEventClass + andEventID:kAEGetURL]; +} + - (void)applicationDidFinishLaunching:(NSNotification*)notification { - [[SUUpdater sharedUpdater] setSendsSystemProfile:YES]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(getArguments:) name:@"GitCommandSent" object:Nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cleanGitAfterErrorMessage:) name:@"ErrorMessageDidEnd" object:Nil]; + + [[SUUpdater sharedUpdater] setSendsSystemProfile:YES]; [[SUUpdater sharedUpdater] setDelegate:self]; + if ([PBGitDefaults useAskPasswd]) { // Make sure Git's SSH password requests get forwarded to our little UI tool: setenv( "SSH_ASKPASS", [[[NSBundle mainBundle] pathForResource: @"gitx_askpasswd" ofType: @""] UTF8String], 1 ); setenv( "DISPLAY", "localhost:0", 1 ); - + } + [self registerServices]; BOOL hasOpenedDocuments = NO; NSArray *launchedDocuments = [[[PBRepositoryDocumentController sharedDocumentController] documents] copy]; - + // Only try to open a default document if there are no documents open already. // For example, the application might have been launched by double-clicking a .git repository, // or by dragging a folder to the app icon @@ -109,11 +129,21 @@ - (void)applicationDidFinishLaunching:(NSNotification*)notification if (![[NSApplication sharedApplication] isActive]) return; +} - // The current directory was not enabled or could not be opened (most likely it’s not a git repository). - // show an open panel for the user to select a repository to view - if ([PBGitDefaults showOpenPanelOnLaunch] && !hasOpenedDocuments) - [[PBRepositoryDocumentController sharedDocumentController] openDocument:self]; +- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent +{ + NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; + NSURL *url = [NSURL URLWithString:urlString]; + + if ([url.host isEqual:@"clone"]) { + NSString * repo = [[url queryArgumentForKey:@"repo"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + + [self showCloneRepository:self]; + + [cloneRepositoryPanel.repositoryURL setStringValue:repo]; + } + } - (void) windowWillClose: sender @@ -133,6 +163,9 @@ - (IBAction)showAboutPanel:(id)sender if (gitversion) [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:gitversion, @"Version", nil]]; + [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:@"GitX (L)", @"ApplicationName", nil]]; + [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:@"(c) Pieter de Bie,2008\n(c) German Laullon,2011\nAnd more...", @"Copyright", nil]]; + #ifdef DEBUG_BUILD [dict addEntriesFromDictionary:[[NSDictionary alloc] initWithObjectsAndKeys:@"GitX (DEBUG)", @"ApplicationName", nil]]; #endif @@ -216,7 +249,7 @@ - (NSManagedObjectModel *)managedObjectModel { return managedObjectModel; } - managedObjectModel = [[NSManagedObjectModel mergedModelFromBundles:nil] retain]; + managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; return managedObjectModel; } @@ -242,7 +275,7 @@ - (NSPersistentStoreCoordinator *) persistentStoreCoordinator { fileManager = [NSFileManager defaultManager]; applicationSupportFolder = [self applicationSupportFolder]; if ( ![fileManager fileExistsAtPath:applicationSupportFolder isDirectory:NULL] ) { - [fileManager createDirectoryAtPath:applicationSupportFolder attributes:nil]; + [fileManager createDirectoryAtPath:applicationSupportFolder withIntermediateDirectories:YES attributes:nil error:nil]; } url = [NSURL fileURLWithPath: [applicationSupportFolder stringByAppendingPathComponent: @"GitTest.xml"]]; @@ -363,6 +396,21 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification [PBGitDefaults setPreviousDocumentPaths:paths]; } } + + [[NSNotificationCenter defaultCenter] removeObserver:self]; +} + +- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender +{ + id dc = [PBRepositoryDocumentController sharedDocumentController]; + + // Reopen last document if user prefers + if ([PBGitDefaults showOpenPanelOnLaunch]) + { + [dc openDocument:self]; + } + + return NO; } /** @@ -371,10 +419,9 @@ - (void)applicationWillTerminate:(NSNotification *)aNotification - (void) dealloc { - [managedObjectContext release], managedObjectContext = nil; - [persistentStoreCoordinator release], persistentStoreCoordinator = nil; - [managedObjectModel release], managedObjectModel = nil; - [super dealloc]; + managedObjectContext = nil; + persistentStoreCoordinator = nil; + managedObjectModel = nil; } @@ -411,9 +458,39 @@ - (IBAction)showHelp:(id)sender - (IBAction)reportAProblem:(id)sender { - [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://gitx.lighthouseapp.com/tickets"]]; + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://github.com/laullon/gitx/issues"]]; } +#pragma mark - Observer methods + +- (void)getArguments:(NSNotification*)notification +{ + notificationUserInfo = [notification userInfo]; +} + + +- (void)cleanGitAfterErrorMessage:(NSNotification*)notification +{ + // When adding a remote occurs an error the remote + // will be set on git and has to be removed to clean the remotes list + [self cleanUpRemotesOnError]; + + + +} + +#pragma mark - Extensions +- (void) cleanUpRemotesOnError +{ + // check, if arguments was to add a remote + if ( ([(NSString*)[notificationUserInfo valueForKey:@"Arg0"] compare:@"remote"] == NSOrderedSame) && + ([(NSString*)[notificationUserInfo valueForKey:@"Arg1"] compare:@"add"] == NSOrderedSame) + ) + { + PBGitRef *remoteRef = [PBGitRef refFromString:[NSString stringWithFormat:@"%@%@", kGitXRemoteRefPrefix,[notificationUserInfo valueForKey:@"Arg3"]]]; + [[notificationUserInfo valueForKey:@"Repository"] deleteRemote:remoteRef]; + } +} @end diff --git a/BMDefines.h b/BMDefines.h new file mode 100644 index 000000000..02a874fab --- /dev/null +++ b/BMDefines.h @@ -0,0 +1,298 @@ +// +// BMDefines.h +// BMScriptTest +// +// Created by Andre Berg on 27.09.09. +// Copyright 2009 Berg Media. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/*! + * @file BMDefines.h + * + * Provides defines mostly for debugging. + * This file may be included by any project as it does not really contain project-specific symbols. + * Consists mainly of stuff I have gathered from multiple sources or defined in my own work to help + * ease debugging and/or cross-platform development. + */ + +#import +#import +#import +#include + +/// @cond HIDDEN +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _BM_DEFINES_H_ +#define _BM_DEFINES_H_ 1 +/// @endcond + + +/*! + * @addtogroup project_defines Project Defines + * @{ + */ + +// Determine runtine environment +#if !defined(__MACOSX_RUNTIME__) && !defined(__GNUSTEP_RUNTIME__) + #if defined(__APPLE__) && defined(__MACH__) && !defined(GNUSTEP) + /*! + * @def MACOSX_RUNTIME + * Determine runtime environment. + * Defined if running on Mac OS X. GNUStep will not have this defined. + */ + #define __MACOSX_RUNTIME__ + #endif // If not Mac OS X, GNUstep? + #if defined(GNUSTEP) && !defined(__MACOSX_RUNTIME__) + /*! + * @def __GNUSTEP_RUNTIME__ + * Determine runtime environment. + * Defined if running GNUStep. Mac OS X will not have this defined. + */ + #define __GNUSTEP_RUNTIME__ + #endif // Not Mac OS X or GNUstep, that's a problem. +#endif // !defined(__MACOSX_RUNTIME__) && !defined(__GNUSTEP_RUNTIME__) + +// If the above did not set the run time environment, error out. +#if !defined(__MACOSX_RUNTIME__) && !defined(__GNUSTEP_RUNTIME__) + #error Unable to determine run time environment, automatic Mac OS X and GNUstep detection failed +#endif + +/*! + * @def ENABLE_MACOSX_GARBAGE_COLLECTION + * Preprocessor definition to enable Mac OS X 10.5 (Leopard) Garbage Collection. + * This preprocessor define enables support for Garbage Collection on Mac OS X 10.5 (Leopard). + * + * Traditional retain / release functionality remains allowing the framework to be used in either + * Garbage Collected enabled applications or reference counting applications. + * + * The framework dynamically picks which mode to use at run-time base on whether or not the + * Garbage Collection system is active. + * + * @sa Garbage Collection Programming Guide + * @sa NSGarbageCollector Class Reference + */ +#if defined(__MACOSX_RUNTIME__) && defined(MAC_OS_X_VERSION_10_5) && defined(__OBJC_GC__) + #define ENABLE_MACOSX_GARBAGE_COLLECTION + #define BM_STRONG_REF __strong + #define BM_WEAK_REF __weak +#else + #define BM_STRONG_REF + #define BM_WEAK_REF +#endif + +#if defined(ENABLE_MACOSX_GARBAGE_COLLECTION) && !defined(MAC_OS_X_VERSION_10_5) +#error The Mac OS X Garbage Collection feature requires at least Mac OS X 10.5 +#endif + + +/*! + * A note to Clang's static analyzer. + * It tells about the returning onwnership intentions of methods. + * The header documentation of Apple follows: + * "Marks methods and functions which return an object that needs to be released by the caller but whose names are not consistent with Cocoa naming rules. The recommended fix to this is the rename the methods or functions, but this macro can be used to let the clang static analyzer know of any exceptions that cannot be fixed." + * + */ +#ifndef NS_RETURNS_RETAINED + #if defined(__clang__) + #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) + #else + #define NS_RETURNS_RETAINED + #endif +#endif + + +// To simplify support for 64bit (and Leopard in general), +// provide the type defines for non Leopard SDKs +#if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) + + // NSInteger/NSUInteger and Max/Mins + #ifndef NSINTEGER_DEFINED + #if __LP64__ || NS_BUILD_32_LIKE_64 + typedef long NSInteger; + typedef unsigned long NSUInteger; + #else + typedef int NSInteger; + typedef unsigned int NSUInteger; + #endif + #define NSIntegerMax LONG_MAX + #define NSIntegerMin LONG_MIN + #define NSUIntegerMax ULONG_MAX + #define NSINTEGER_DEFINED 1 + #endif // NSINTEGER_DEFINED + + // CGFloat + #ifndef CGFLOAT_DEFINED + #if defined(__LP64__) && __LP64__ + // This really is an untested path (64bit on Tiger?) + typedef double CGFloat; + #define CGFLOAT_MIN DBL_MIN + #define CGFLOAT_MAX DBL_MAX + #define CGFLOAT_IS_DOUBLE 1 + #else /* !defined(__LP64__) || !__LP64__ */ + typedef float CGFloat; + #define CGFLOAT_MIN FLT_MIN + #define CGFLOAT_MAX FLT_MAX + #define CGFLOAT_IS_DOUBLE 0 + #endif /* !defined(__LP64__) || !__LP64__ */ + #define CGFLOAT_DEFINED 1 + #endif // CGFLOAT_DEFINED + + // NS_INLINE + #if !defined(NS_INLINE) + #if defined(__GNUC__) + #define NS_INLINE static __inline__ __attribute__((always_inline)) + #elif defined(__MWERKS__) || defined(__cplusplus) + #define NS_INLINE static inline + #elif defined(_MSC_VER) + #define NS_INLINE static __inline + #elif defined(__WIN32__) + #define NS_INLINE static __inline__ + #endif + #endif + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 + +/*! + * @def BM_C99(keyword) + * C99 conformance defines. + * Make it possible to safely use keywords and features of the C99 standard. + * @param keyword a C99 keyword (e.g. restrict) + */ +#if __STDC_VERSION__ >= 199901L + #define BM_C99(keyword) keyword +#else + #define BM_C99(keyword) +#endif + +/*! + * @def BM_REQUIRES_NIL_TERMINATION + * Used to mark variadic methods and functions as requiring nil termination. + * Nil termination means the last argument of their variable argument list must be nil. + */ +#if !defined(BM_REQUIRES_NIL_TERMINATION) + #if TARGET_OS_WIN32 + #define BM_REQUIRES_NIL_TERMINATION + #else + #if defined(__APPLE_CC__) && (__APPLE_CC__ >= 5549) + #define BM_REQUIRES_NIL_TERMINATION __attribute__((sentinel(0,1))) + #else + #define BM_REQUIRES_NIL_TERMINATION __attribute__((sentinel)) + #endif + #endif +#endif + +/*! + * @def BM_EXTERN + * Defines for the extern keyword. + * Makes it possible to use extern in the proper sense in C++ context included. + */ +/*! + * @def BM_PRIVATE_EXTERN + * Defines for the __private_extern__ Apple compiler directive. + * Makes a symbol public in the binrary (e.g. a library), but hidden outside of it. + */ +#ifdef __cplusplus + #define BM_EXTERN extern "C" + #define BM_PRIVATE_EXTERN __private_extern__ +#else + #define BM_EXTERN extern + #define BM_PRIVATE_EXTERN __private_extern__ +#endif + +/*! + * @def BM_ATTRIBUTES + * Macro wrapper around GCC __attribute__ syntax. + * @note When a compiler other than GCC 4+ is used, #BM_ATTRIBUTES evaluates to an empty string, removing itself and its arguments from the code to be compiled.

+ */ +/*! + * @def BM_EXPECTED + * Macro wrapper around GCC __builtin_expect syntax. + * + * From GCC docs: "You may use __builtin_expect to provide the compiler with branch prediction information. In general, you should prefer to use actual profile feedback for this (-fprofile-arcs), as programmers are notoriously bad at predicting how their programs actually perform. However, there are applications in which this data is hard to collect. + * + * The return value is the value of exp, which should be an integral expression. The value of c must be a compile-time constant. The semantics of the built-in are that it is expected that exp == c." + * + * And from RegexKit Framework docs (the origin of this macro): + * + *
Important:
BM_EXPECTED should only be used when the likelihood of the prediction is nearly certain. DO NOT GUESS.
+ * + * BM_EXPECTED [...] is used to provide the compiler with branch prediction information for conditional statements. + * + * An example of an appropriate use is parameter validation checks at the start of a function, such as (aPtr == NULL). Since callers are always expected to pass a valid pointer, the likelihood of the conditional evaluating to true is extremely unlikely. This allows the compiler to schedule instructions to minimize branch miss-prediction penalties. For example: +
if(BM_EXPECTED((aPtr == NULL), 0)) { abort(); }
+ * + * @note If a compiler other than GCC 4+ is used then the macro leaves the conditional expression unaltered. + */ +#if defined (__GNUC__) && (__GNUC__ >= 4) + #define BM_STATIC_INLINE static __inline__ __attribute__((always_inline)) + #define BM_STATIC_PURE_INLINE static __inline__ __attribute__((always_inline, pure)) + #define BM_EXPECTED(cond, expect) __builtin_expect(cond, expect) + #define BM_ALIGNED(boundary) __attribute__ ((aligned(boundary))) + #define BM_ATTRIBUTES(attr, ...) __attribute__((attr, ##__VA_ARGS__)) +#else + #define BM_STATIC_INLINE static __inline__ + #define BM_STATIC_PURE_INLINE static __inline__ + #define BM_EXPECTED(cond, expect) cond + #define BM_ALIGNED(boundary) + #define BM_ATTRIBUTES(attr, ...) +#endif + + +/*! + * @def BM_DEBUG_RETAIN_INIT + * Defines a macro which supplies replacement methods for -[retain] and -[release]. + * This macro is normally used in a global context (e.g. outside main) and followed by BM_DEBUG_RETAIN_SWIZZLE(className) in a local context, which then actually registers the replacement for the Class 'className' with the runtime. + * @attention This is only intended for debugging purposes. Has no effect if Garbage Collection is enabled. + */ +#define BM_DEBUG_RETAIN_INIT \ + IMP oldRetain;\ + IMP oldRelease;\ + id newRetain(id self, SEL _cmd) {\ + NSUInteger rc = [self retainCount];\ + NSLog(@"%s[0x%x]: retain, rc = %d -> %d",\ + class_getName([self class]), self, rc, rc + 1);\ + return (*oldRetain)(self, _cmd);\ + }\ + void newRelease(id self, SEL _cmd) {\ + NSUInteger rc = [self retainCount];\ + NSLog(@"%s[0x%x]: retain, rc = %d -> %d", \ + class_getName([self class]), self, rc, rc - 1);\ + (*oldRetain)(self, _cmd);\ + } + +/*! + * @def BM_DEBUG_RETAIN_SWIZZLE(className) + * Swizzles (or replaces) the methods defined by #BM_DEBUG_RETAIN_INIT for className. + * This macro is normally used in a (function) local scope, provided a #BM_DEBUG_RETAIN_INIT declaration at the beginning of the file (in global context). BM_DEBUG_RETAIN_SWIZZLE(className) then actually registers the replacements defined by #BM_DEBUG_RETAIN_INIT for the Class 'className' with the runtime. + * @attention This is only intended for debugging purposes. Has no effect if Garbage Collection is enabled. + * @param className the name of the class to replace the methods for (e.g. [SomeClass class]). + */ +#define BM_DEBUG_RETAIN_SWIZZLE(className) \ + oldRetain = class_getMethodImplementation((className), @selector(retain));\ + class_replaceMethod((className), @selector(retain), (IMP)&newRetain, "@@:");\ + oldRelease = class_getMethodImplementation((className), @selector(release));\ + class_replaceMethod((className), @selector(release), (IMP)&newRelease, "v@:"); + +/*! + * @} + */ + +#endif // _BM_DEFINES_H_ + +#ifdef __cplusplus +} /* extern "C" */ +#endif \ No newline at end of file diff --git a/BMScript.h b/BMScript.h new file mode 100644 index 000000000..9fa442852 --- /dev/null +++ b/BMScript.h @@ -0,0 +1,998 @@ +// +// BMScript.h +// BMScriptTest +// +// Created by Andre Berg on 11.09.09. +// Copyright 2009 Berg Media. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// MARK: Docs: Mainpage + +/*! + * @mainpage BMScript: Harness The Power Of Shell Scripts + *
+ * @par Introduction + * + * BMScript is an Objective-C class set to make it easier to utilize the + * power and flexibility of a whole range of scripting languages that already + * come with modern Macs. BMScript does not favor any particular scripting + * language or UNIX™ command line tool for that matter, instead it was written + * as an abstraction layer to NSTask, and as such supports any command line tool, + * provided that it is available on the target system. + * + * @par Usage + * + * BMScript can be used in two ways: + * + * -# Use it directly + * -# Guided by the BMScriptLanguageProtocol, make a subclass from it + * + * The easiest way to use BMScript is, of course, to instanciate it directly: + * + * @include bmScriptCreationMethods.m + * + * You typically use the designated initializer for which you supply the script + * source and script options yourself.
+ * The options dictionary then looks like this: + * + * @include bmScriptOptionsDictionary.m + * + * There's two constant keys. These are the only keys you need to define values for. + * #BMScriptOptionsTaskLaunchPathKey stores the path to the tool's executable and + * #BMScriptOptionsTaskArgumentsKey is a nil-terminated variable list of parameters + * to be used as arguments to the task which will load and execute the tool found at + * the launch path specified for the other key. + * + * It is very important to note that the script source string should NOT be + * supplied in the array for the #BMScriptOptionsTaskArgumentsKey, as it will be added + * later by the class after performing tests and delegation which could alter the script + * in ways needed to safely execute it. This is in the delegate object's responsibility. + * + * A macro function called #BMSynthesizeOptions(path, args) is available to ease + * the declaration of the options.
+ * Here is the definition: + * + * @include bmScriptSynthesizeOptions.m + * + *
+ *
+ *
+ *
Important:
+ *
+ * Don't forget the nil at the end even + * if you don't need to supply any task arguments. + *
+ *
+ *
+ *
+ * + * If you initialize BMScript directly without specifying options and script source + * (e.g. using [[%BMScript alloc] init]) the options + * will default to BMSynthesizeOptions(@"/bin/echo", @"") + * and the script source will default to @"' - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -
hola +
+
\ No newline at end of file diff --git a/html/views/commit/commit.js b/html/views/commit/commit.js index 849d9d5ca..2c6cda6a0 100644 --- a/html/views/commit/commit.js +++ b/html/views/commit/commit.js @@ -9,7 +9,7 @@ var showNewFile = function(file) var contents = Index.diffForFile_staged_contextLines_(file, false, contextLines); if (!contents) { - notify("Can not display changes (Binary file?)", -1); + notify("Cannot display changes (file is binary or too large)", -1); diff.innerHTML = ""; return; } @@ -76,15 +76,19 @@ var showFileChanges = function(file, cached) { var setSelectHandlers = function() { document.onmousedown = function(event) { + if (!event.metaKey) + return; if(event.which != 1) return false; deselect(); currentSelection = false; } - document.onselectstart = function () {return false;}; /* prevent normal text selection */ var list = document.getElementsByClassName("lines"); document.onmouseup = function(event) { + if (!event.metaKey) + return; + // Handle button releases outside of lines list for (i = 0; i < list.length; ++i) { file = list[i]; @@ -96,6 +100,9 @@ var setSelectHandlers = function() for (i = 0; i < list.length; ++i) { var file = list[i]; file.ondblclick = function (event) { + if (!event.metaKey) + return; + var file = event.target.parentNode; if (file.id = "selected") file = file.parentNode; @@ -110,6 +117,8 @@ var setSelectHandlers = function() }; file.onmousedown = function(event) { + if (!event.metaKey) + return; if (event.which != 1) return false; var elem_class = event.target.getAttribute("class") @@ -150,6 +159,8 @@ var setSelectHandlers = function() file.onmouseover = function(event2) { + if (!event.metaKey) + return; showSelection(file, event.srcElement, event2.target); return false; }; diff --git a/html/views/commit/index.html b/html/views/commit/index.html index 54698daa8..e04c0a646 100644 --- a/html/views/commit/index.html +++ b/html/views/commit/index.html @@ -1,15 +1,16 @@ Diff for file - - - - - + + + + + + + - - - + + diff --git a/html/views/commit/test.html b/html/views/commit/test.html new file mode 100644 index 000000000..9f9b3c352 --- /dev/null +++ b/html/views/commit/test.html @@ -0,0 +1,56 @@ + + + Diff for file + + + + + + + + + + + + + +

+ + Context: + Nothing to commit + +

+ + + + +
+ Nothing to commit (working directory clean) +
+
+ + diff --git a/html/views/diff/diffWindow.css b/html/views/diff/diffWindow.css index e9a512220..6cf0544c7 100644 --- a/html/views/diff/diffWindow.css +++ b/html/views/diff/diffWindow.css @@ -1,14 +1,168 @@ -#message { - margin-left: 20px; - margin-right: 20px; - margin-top: 40px; +body { + margin: 0; + padding: 0; +} + +#diffs { + width: 100%; + display: block; + overflow: auto; +} + +#diff { + display: block; + overflow: auto; +} + +.diff-header, .diff-body { + font-family: Menlo, Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; + border-collapse: collapse; + border-style: solid; + border-color: #8f8f8f; + -webkit-box-shadow:3px 3px 3px #ccc; + width: 98%; + overflow: auto; +} + +.diff-header { + border-width: 1px 1px 0 1px; + margin: auto auto 0 1%; +} + +.diff-body { + border-width: 0 1px 1px 1px; + margin: auto auto 20px 1%; +} + +.diff-header table.diff { + width: 100%; +} + +table.diff { + border-collapse: collapse; +} + +table.diff tr td { + font-size: 11px; + white-space: pre; + padding-left: 5px; + padding-right: 5px; +} + +table.diff td.code { + width: 100%; + border-left: 2px solid #d0d0d0; +} + +table.diff tr.header td { + border-bottom: 1px solid #8f8f8f; + padding: 5px; +} + +table.diff tr td.l { + border-right: 1px solid #909090; +} + +table.diff tr.r { + background-color: rgba(0,255,0,0.1); +} + +table.diff tr.l { + background-color: rgba(255,0,0,0.1); +} + +table.diff tr.r td.code { + border-left-color: rgba(0,255,0,0.2); +} + +table.diff tr.l td.code { + border-left-color: rgba(255,0,0,0.2); +} + +table.diff thead tr td p { + margin: 0; +} + +table.diff thead { + background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, rgba(206,206,206,1)), color-stop(1, rgba(166,166,166,1))); +} + +table.diff thead tr td { + padding: 5px; +} + +table.diff tbody tr.header { + background-image: -webkit-gradient(linear,left top,left bottom, color-stop(0, rgba(244, 244, 244,1)), color-stop(1, rgba(215,215,215,1))); +} + +table.diff .filemerge { + float: right; text-align: center; - font-size: 200%; - padding: 20px; - width: auto; +} + +#filelist { + font-size: 13px; + white-space: nowrap; + width: 100%; + padding: 0 20px; + border-collapse: collapse; + margin-bottom: 10px; +} + +#filelist tr td { + border-bottom: 1px solid #ccc; + border-top: 1px solid #ccc; +} + +#filelist a { + margin-left: 10px; + padding-left: 20px; + text-decoration: none; +} + +#filelist a:hover { + text-decoration: underline; +} + +#filelist a.A { + background: url(../../images/added.png) no-repeat 0 center; +} + +#filelist a.D { + background: url(../../images/removed.png) no-repeat 0 center; +} + +#filelist a.M { + background: url(../../images/modified.png) no-repeat 0 center; +} + +#filelist a.R,#filelist a.C { + background: url(../../images/renamed.png) no-repeat 0 center; +} + +#filelist span.add,#filelist span.rem { + display: block; + height: 10px; + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; + float: right; + clear: both; +} + +#filelist span.add { + background-color: rgba(0, 255, 0, 0.199219); +} + +#filelist span.rem { + background-color: rgba(255, 0, 0, 0.199219); +} - background-color: #B4D7FF; - border: 2px solid #45A1FE; +#filelist td.bar { + width: 50%; + display: block; +} - -webkit-border-radius: 10px; -} \ No newline at end of file +#filelist td.add,#filelist td.rem { + width: 1%; + text-align: right; +} diff --git a/html/views/diff/diffWindow.js b/html/views/diff/diffWindow.js index 6cef3d732..cb33f9283 100644 --- a/html/views/diff/diffWindow.js +++ b/html/views/diff/diffWindow.js @@ -1,8 +1,19 @@ -// for diffs shown in the PBDiffWindow - var setMessage = function(message) { $("message").style.display = ""; $("message").innerHTML = message.escapeHTML(); $("diff").style.display = "none"; } +var showFile = function(txt) { + $("diff").style.display = ""; + $("diff").innerHTML = txt; + $("message").style.display = "none"; +} + +// TODO: need to be refactoring +var openFileMerge = function(file,sha,sha2) { + alert(file); + alert(sha); + alert(sha2); + Controller.openFileMerge_sha_sha2_(file,sha,sha2); +} diff --git a/html/views/diff/index.html b/html/views/diff/index.html index dc4e6f306..f31260fa8 100644 --- a/html/views/diff/index.html +++ b/html/views/diff/index.html @@ -1,25 +1,17 @@ - - Details for commit - - - - - - - - - - - - - - -
- + + + + + + + + + + + + +
+
+ + diff --git a/html/views/fileview/fileview.js b/html/views/fileview/fileview.js index a8abad62d..1bb739e5b 100644 --- a/html/views/fileview/fileview.js +++ b/html/views/fileview/fileview.js @@ -1,6 +1,102 @@ -var showFile = function(txt) { +var showFile = function(txt, fileName) { $("source").style.display = ""; - $("source").innerHTML="
"+txt+"
"; + var suffix_map = { + "m": "objc", + "h": "objc", + + "rb": "ruby", + "rbx": "ruby", + "rjs": "ruby", + "Rakefile": "ruby", + "rake": "ruby", + "gemspec": "ruby", + "irbrc": "ruby", + "capfile": "ruby", + + "xml": "xml", + "tld": "xml", + "jsp": "xml", + "pt": "xml", + "cpt": "xml", + "dtml": "xml", + "rss": "xml", + "opml": "xml", + "xsl": "xml", + "xslt": "xml", + + "js": "javascript", + "htc": "javascript", + "jsx": "javascript", + "jscript": "javascript", + "javascript": "javascript", + + "sql": "sql", + "ddl": "sql", + "dml": "sql", + + "sass": "sass", + "scss": "sass", + + "sh": "bash", + "bash": "bash", + "zsh": "bash", + "bashrc": "bash", + "bash_profile": "bash", + "bash_login": "bash", + "profile": "bash", + "bash_logout": "bash", + + "diff": "diff", + "patch": "diff", + + "java": "java", + "bsh": "java", + + "css": "css", + "css": "css.erb", + "pl": "perl", + "pm": "perl", + "pod": "perl", + "t": "perl", + "PL": "perl", + + "erl": "erlang", + "hrl": "erlang", + + "php": "php", + + "py": "python", + "rpy": "python", + "pyw": "python", + "cpy": "python", + "SConstruct": "python", + "Sconstruct": "python", + "sconstruct": "python", + "SConscript": "python", + + "cc": "cpp", + "cpp": "cpp", + "cp": "cpp", + "cxx": "cpp", + "c++":"cpp", + "C": "cpp", + "h": "cpp", + "hh": "cpp", + "hpp": "cpp", + "cpp": "h++", + "c": "cpp" + } + var brush = "objc"; + var suffix = ""; + if (fileName && fileName != '') { + suffix = fileName.substr(fileName.lastIndexOf('.') + 1); + } + + brush = suffix_map[suffix]; + + $("source").innerHTML="
" + txt + "
"; + $("source").style.display = ""; + $("message").style.display = "none"; SyntaxHighlighter.defaults['toolbar'] = false; SyntaxHighlighter.highlight(); @@ -8,9 +104,24 @@ var showFile = function(txt) { return; } +var setMessage = function(message) { + $("message").style.display = ""; + $("message").innerHTML = message.escapeHTML(); + $("source").style.display = "none"; +} + + var test=function(txt) { SyntaxHighlighter.defaults['toolbar'] = false; SyntaxHighlighter.highlight(); return; } + +var get_keys = function(obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + } + return keys; +} diff --git a/html/views/fileview/index.html b/html/views/fileview/index.html index 6dfb4cdcd..689a9dc9c 100644 --- a/html/views/fileview/index.html +++ b/html/views/fileview/index.html @@ -1,14 +1,45 @@ - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
\ No newline at end of file diff --git a/html/views/fileview/index_test.html b/html/views/fileview/index_test.html deleted file mode 100644 index c49766e56..000000000 --- a/html/views/fileview/index_test.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - -
-
-//
-//  AppController.h
-//  MGScopeBar
-//
-//  Created by Matt Gemmell on 16/03/2008.
-//
-
-/* dhfas fldsa */
-
-/*
-fjdsahf dsaf dlsaf jd;sa
-fdjksal; fjhdsa
-*/
-
-#import <Cocoa/Cocoa.h>
-#import "MGScopeBarDelegateProtocol.h"
-
-
-/* dhfas fldsa */
-
-@interface AppController : NSObject  {
-	IBOutlet NSTextField *labelField;
-	IBOutlet MGScopeBar *scopeBar;
-	IBOutlet NSView *accessoryView;
-	NSMutableArray *groups;
-}
-
-@property(retain) NSMutableArray *groups;
-
-@end
-
- -
- - \ No newline at end of file diff --git a/html/views/history/history.css b/html/views/history/history.css index 7d855aa55..373c5bfea 100644 --- a/html/views/history/history.css +++ b/html/views/history/history.css @@ -1,5 +1,33 @@ +.clearfix:after { + visibility: hidden; + display: block; + font-size: 0; + content: " "; + clear: both; + height: 0; +} + +.clearfix { + display: inline-block; +} + +/* start commented backslash hack \*/ + +* html .clearfix { + height: 1%; +} + +.clearfix { + display: block; +} + +/* close commented backslash hack */ + body { + background-color: #f2f2f2; font-family: 'Lucida Grande'; + margin: 0px; + padding: 0px; } #commit_header { @@ -10,7 +38,7 @@ body { } #commit_header tr { - vertical-align: top; + vertical-align: top; } #authorTable { @@ -18,8 +46,10 @@ body { } #rightcontent { - float: right; + float: none; margin: 5px; + position: absolute; + right: 0; } #buttons { @@ -27,27 +57,24 @@ body { } a.servicebutton { - display: block; - width: 80px; - padding: 2px; - margin-bottom: 4px; - - border: 1px solid #3465a4; - background-color: #cce5ff; - color: #204a87; - - font-size: 65%; - text-decoration: none; - text-align: center; - - -webkit-border-radius: 2px; + display: block; + width: 80px; + padding: 2px; + margin-bottom: 4px; + border: 1px solid #3465a4; + background-color: #cce5ff; + color: #204a87; + font-size: 65%; + text-decoration: none; + text-align: center; + -webkit-border-radius: 2px; } .gravatar { padding: 0.1em; - border: solid gray 1px; -webkit-border-radius: 2px; + display: none; } .gravatar img { @@ -55,26 +82,31 @@ a.servicebutton { height: 2.9em; max-height: 60px; max-width: 60px; + display: none; } .property_name { width: 6em; - color:#7F7F7F; + color: #7F7F7F; text-align: right; font-weight: bold; } - #message_files { margin: 5px; padding-left: 1em; width: auto; } -#message { - font-family: Menlo, Monaco; - white-space: pre-wrap; - padding-top: 10px; +#header p.subject { + font-size: 13px; + padding: 5px; + float: none; + font-weight: bold; +} + +p.subjectDetail { + padding: 5px; } #files { @@ -104,20 +136,21 @@ a.servicebutton { } .clear_both { - clear:both; - display:block; - height:1px; - line-height:0; - margin:1em; - visibility:hidden; + clear: both; + display: block; + height: 1px; + line-height: 0; + margin: 1em; + visibility: hidden; } #details { - font-family: Monaco; + font-family: Menlo; font-size: 10px; overflow: hidden; width: 600px; } + hr { border: 0; height: 1px; @@ -160,47 +193,100 @@ a.showdiff { background-color: #fca64f; } -/* -div.button -{ - color: #666666; +#header { + font-size: 13px; + background-image: -webkit-gradient(linear,left top,left bottom, color-stop(.7, #EAF2f6), color-stop(1, #e3ebf3)); +} - font-size: 60%; - text-align: center; +#header table.references td{ + text-align:right; +} + +#header table.references a, +#header table.references p{ + font-family: Menlo, Consolas, 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace; +} + +#header p.time { + margin-top: 2px; + font-size: 11px; + white-space: nowrap; +} + +#header p.name { + font-size: 13px; + white-space: nowrap; +} - width: 70px; +#header span.rol,p.time { + color: gray; - margin-right: 10px; +} +#header img.avatar { + float: left; padding: 2px; + border: 1px solid black; + margin: 0 5px 5px; +} + +#header table.references { + float: right; + font-size: 12px; + margin: 5px; +} +#header div.user { float: left; - clear: both; + clear: left; +} - border: 1px solid; - -webkit-border-radius: 3px; +#header p { + margin: 0; } -div.created -{ - background-color: #ccffcc; - border-color: #66ff66; +#header div#badges { + clear: left; + float: left; + margin: 5px; + padding-bottom: 5px; } -div.changed -{ - background-color: #ffcc99; - border-color: #ff9933; +.filemerge { + float: right; + text-align: center; } -div.deleted -{ - background-color: #ffcccc; - border-color: #ff6666; +/* scrollbars */ + +::-webkit-scrollbar { + width: 6px; + height: 6px; } -div.renamed -{ - // No colour needed right now. +::-webkit-scrollbar-button:start:decrement, +::-webkit-scrollbar-button:end:increment { + display: block; + height: 10px; } -*/ + +::-webkit-scrollbar-button:vertical:increment { + background-color: #fff; +} + +::-webkit-scrollbar-track-piece { + background-color: #eee; + -webkit-border-radius: 3px; +} + +::-webkit-scrollbar-thumb:vertical { + height: 50px; + background-color: #ccc; + -webkit-border-radius: 3px; +} + +::-webkit-scrollbar-thumb:horizontal { + width: 50px; + background-color: #ccc; + -webkit-border-radius: 3px; +} \ No newline at end of file diff --git a/html/views/history/history.js b/html/views/history/history.js index 225e590fd..918b0b310 100644 --- a/html/views/history/history.js +++ b/html/views/history/history.js @@ -1,277 +1,14 @@ -var commit; - -// Create a new Commit object -// obj: PBGitCommit object -var Commit = function(obj) { - this.object = obj; - - this.refs = obj.refs(); - this.author_name = obj.author; - this.committer_name = obj.committer; - this.sha = obj.realSha(); - this.parents = obj.parents; - this.subject = obj.subject; - this.notificationID = null; - - // TODO: - // this.author_date instant - - // This can be called later with the output of - // 'git show' to fill in missing commit details (such as a diff) - this.parseDetails = function(details) { - this.raw = details; - - var diffStart = this.raw.indexOf("\ndiff "); - var messageStart = this.raw.indexOf("\n\n") + 2; - - if (diffStart > 0) { - this.message = this.raw.substring(messageStart, diffStart).replace(/^ /gm, "").escapeHTML(); - this.diff = this.raw.substring(diffStart); - } else { - this.message = this.raw.substring(messageStart).replace(/^ /gm, "").escapeHTML(); - this.diff = ""; - } - this.header = this.raw.substring(0, messageStart); - - if (typeof this.header !== 'undefined') { - var match = this.header.match(/\nauthor (.*) <(.*@.*|.*)> ([0-9].*)/); - if (typeof match !== 'undefined' && typeof match[2] !== 'undefined') { - if (!(match[2].match(/@[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/))) - this.author_email = match[2]; - - if (typeof match[3] !== 'undefined') - this.author_date = new Date(parseInt(match[3]) * 1000); - - match = this.header.match(/\ncommitter (.*) <(.*@.*|.*)> ([0-9].*)/); - if (typeof match[2] !== 'undefined') - this.committer_email = match[2]; - if (typeof match[3] !== 'undefined') - this.committer_date = new Date(parseInt(match[3]) * 1000); - } - } - } - - this.reloadRefs = function() { - this.refs = this.object.refs(); - } - -}; - - -var confirm_gist = function(confirmation_message) { - if (!Controller.isFeatureEnabled_("confirmGist")) { - gistie(); - return; - } - - // Set optional confirmation_message - confirmation_message = confirmation_message || "Yes. Paste this commit."; - var deleteMessage = Controller.getConfig_("github.token") ? " " : "You might not be able to delete it after posting.
"; - var publicMessage = Controller.isFeatureEnabled_("publicGist") ? "public" : "private"; - // Insert the verification links into div#notification_message - var notification_text = 'This will create a ' + publicMessage + ' paste of your commit to http://gist.github.com/
' + - deleteMessage + - 'Are you sure you want to continue?

' + - 'No. Cancel. | ' + - '' + confirmation_message + ''; - - notify(notification_text, 0); - // Hide img#spinner, since it?s visible by default - $("spinner").style.display = "none"; -} - -var gistie = function() { - notify("Uploading code to Gistie..", 0); - - parameters = { - "file_ext[gistfile1]": "patch", - "file_name[gistfile1]": commit.object.subject.replace(/[^a-zA-Z0-9]/g, "-") + ".patch", - "file_contents[gistfile1]": commit.object.patch(), - }; - - // TODO: Replace true with private preference - token = Controller.getConfig_("github.token"); - login = Controller.getConfig_("github.user"); - if (token && login) { - parameters.login = login; - parameters.token = token; - } - if (!Controller.isFeatureEnabled_("publicGist")) - parameters.private = true; - - var params = []; - for (var name in parameters) - params.push(encodeURIComponent(name) + "=" + encodeURIComponent(parameters[name])); - params = params.join("&"); - - var t = new XMLHttpRequest(); - t.onreadystatechange = function() { - if (t.readyState == 4 && t.status >= 200 && t.status < 300) { - if (m = t.responseText.match(//)) - notify("Code uploaded to gistie #" + m[1] + "", 1); - else { - notify("Pasting to Gistie failed :(.", -1); - Controller.log_(t.responseText); - } - } - } - - t.open('POST', "https://gist.github.com/gists"); - t.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); - t.setRequestHeader('Accept', 'text/javascript, text/html, application/xml, text/xml, */*'); - t.setRequestHeader('Content-type', 'application/x-www-form-urlencoded;charset=UTF-8'); - - try { - t.send(params); - } catch(e) { - notify("Pasting to Gistie failed: " + e, -1); - } -} - -var setGravatar = function(email, image) { - if(Controller && !Controller.isFeatureEnabled_("gravatar")) { - image.src = ""; - return; - } - - if (!email) { - image.src = "http://www.gravatar.com/avatar/?d=wavatar&s=60"; - return; - } - - image.src = "http://www.gravatar.com/avatar/" + - hex_md5(email.toLowerCase().replace(/ /g, "")) + "?d=wavatar&s=60"; -} - +// TODO: need to be refactoring var selectCommit = function(a) { Controller.selectCommit_(a); } -// Relead only refs -var reload = function() { - $("notification").style.display = "none"; - commit.reloadRefs(); - showRefs(); -} - -var showRefs = function() { - var refs = $("refs"); - if (commit.refs) { - refs.parentNode.style.display = ""; - refs.innerHTML = ""; - for (var i = 0; i < commit.refs.length; i++) { - var ref = commit.refs[i]; - refs.innerHTML += '' + ref.shortName() + ' '; - } - } else - refs.parentNode.style.display = "none"; -} - -var loadCommit = function(commitObject, currentRef) { - // These are only the things we can do instantly. - // Other information will be loaded later by loadCommitDetails, - // Which will be called from the controller once - // the commit details are in. - - if (commit && commit.notificationID) - clearTimeout(commit.notificationID); - - commit = new Commit(commitObject); - commit.currentRef = currentRef; - - $("commitID").innerHTML = commit.sha; - $("authorID").innerHTML = commit.author_name; - $("subjectID").innerHTML = commit.subject.escapeHTML(); - $("diff").innerHTML = "" - $("message").innerHTML = "" - $("files").innerHTML = "" - $("date").innerHTML = "" - showRefs(); - - for (var i = 0; i < $("commit_header").rows.length; ++i) { - var row = $("commit_header").rows[i]; - if (row.innerHTML.match(/Parent:/)) { - row.parentNode.removeChild(row); - --i; - } - } - - // Scroll to top - scroll(0, 0); - - if (!commit.parents) - return; - - for (var i = 0; i < commit.parents.length; i++) { - var newRow = $("commit_header").insertRow(-1); - newRow.innerHTML = "Parent:" + - "" + - commit.parents[i].string + ""; - } - - commit.notificationID = setTimeout(function() { - if (!commit.fullyLoaded) - notify("Loading commit…", 0); - commit.notificationID = null; - }, 500); - -} - -var showDiff = function() { - - $("files").innerHTML = ""; - - // Callback for the diff highlighter. Used to generate a filelist - var newfile = function(name1, name2, id, mode_change, old_mode, new_mode) { - var img = document.createElement("img"); - var p = document.createElement("p"); - var link = document.createElement("a"); - link.setAttribute("href", "#" + id); - p.appendChild(link); - var finalFile = ""; - if (name1 == name2) { - finalFile = name1; - img.src = "../../images/modified.png"; - img.title = "Modified file"; - p.title = "Modified file"; - if (mode_change) - p.appendChild(document.createTextNode(" mode " + old_mode + " -> " + new_mode)); - } - else if (name1 == "/dev/null") { - img.src = "../../images/added.png"; - img.title = "Added file"; - p.title = "Added file"; - finalFile = name2; - } - else if (name2 == "/dev/null") { - img.src = "../../images/removed.png"; - img.title = "Removed file"; - p.title = "Removed file"; - finalFile = name1; - } - else { - img.src = "../../images/renamed.png"; - img.title = "Renamed file"; - p.title = "Renamed file"; - finalFile = name2; - p.insertBefore(document.createTextNode(name1 + " -> "), link); - } - - link.appendChild(document.createTextNode(finalFile)); - link.setAttribute("representedFile", finalFile); - - p.insertBefore(img, link); - $("files").appendChild(p); - } - - var binaryDiff = function(filename) { - if (filename.match(/\.(png|jpg|icns|psd)$/i)) - return 'Display image'; - else - return "Binary file differs"; - } - - highlightDiff(commit.diff, $("diff"), { "newfile" : newfile, "binaryFile" : binaryDiff }); +// TODO: need to be refactoring +var openFileMerge = function(file,sha,sha2) { + alert(file); + alert(sha); + alert(sha2); + Controller.openFileMerge_sha_sha2_(file,sha,sha2); } var showImage = function(element, filename) @@ -280,58 +17,11 @@ var showImage = function(element, filename) return false; } -var enableFeature = function(feature, element) -{ - if(!Controller || Controller.isFeatureEnabled_(feature)) { - element.style.display = ""; - } else { - element.style.display = "none"; - } -} - -var enableFeatures = function() -{ - enableFeature("gist", $("gist")) - enableFeature("gravatar", $("author_gravatar").parentNode) - enableFeature("gravatar", $("committer_gravatar").parentNode) +var showCommit = function(data){ + $("commit").innerHTML=data; } -var loadCommitDetails = function(data) -{ - commit.parseDetails(data); - - if (commit.notificationID) - clearTimeout(commit.notificationID) - else - $("notification").style.display = "none"; - - var formatEmail = function(name, email) { - return email ? name + " <" + email + ">" : name; - } - - $("authorID").innerHTML = formatEmail(commit.author_name, commit.author_email); - $("date").innerHTML = commit.author_date; - setGravatar(commit.author_email, $("author_gravatar")); - - if (commit.committer_name != commit.author_name) { - $("committerID").parentNode.style.display = ""; - $("committerID").innerHTML = formatEmail(commit.committer_name, commit.committer_email); - - $("committerDate").parentNode.style.display = ""; - $("committerDate").innerHTML = commit.committer_date; - setGravatar(commit.committer_email, $("committer_gravatar")); - } else { - $("committerID").parentNode.style.display = "none"; - $("committerDate").parentNode.style.display = "none"; - } - - $("message").innerHTML = commit.message.replace(/\n/g,"
"); - - if (commit.diff.length < 200000) - showDiff(); - else - $("diff").innerHTML = "This is a large commit. Click here or press 'v' to view."; - - hideNotification(); - enableFeatures(); +var showFullDiff = function() { + Controller.showLongDiff(); + Controller.updateView(); } diff --git a/html/views/history/index.html b/html/views/history/index.html index cc8d4a286..d8c62c92c 100644 --- a/html/views/history/index.html +++ b/html/views/history/index.html @@ -1,74 +1,19 @@ - - Details for commit - - - - - + + Details for commit + + + - - - + + + + + + + - - - - - - - - - - - - - - - - - - -
SHA:
- - - - - - - - - - - - - - - - - - -
Author:
Date:
Committer:
Date:
-
Subject:
Refs:
- -
-
-
-
-
- -
- + +
+ + diff --git a/html/views/log/index.html b/html/views/log/index.html index 593d6b13e..50a69f3d9 100644 --- a/html/views/log/index.html +++ b/html/views/log/index.html @@ -1,19 +1,17 @@ - - Details for commit - - - - - - - - - - - - -
- + + + + + + + + + + + + +
+
+ + diff --git a/html/views/log/log.js b/html/views/log/log.js index f484fe612..b66357309 100644 --- a/html/views/log/log.js +++ b/html/views/log/log.js @@ -3,8 +3,14 @@ var selectCommit = function(a) { return false; } +var setMessage = function(message) { + $("message").style.display = ""; + $("message").innerHTML = message.escapeHTML(); + $("log").style.display = "none"; +} + var showFile = function(txt) { + $("log").innerHTML = txt; $("log").style.display = ""; - $("log").innerHTML=txt; - return; + $("message").style.display = "none"; } diff --git a/html/views/log/test.html b/html/views/log/test.html deleted file mode 100644 index 5e8d6e14f..000000000 --- a/html/views/log/test.html +++ /dev/null @@ -1,200 +0,0 @@ - - Details for commit - - - - - - - - - - - - -
- - - - -
Commit:703782163ddb653789c304e396eadb31f541864f
Author:Pieter de Bie
Date:10 months ago
-
PBChangedFile: Add assert to make sure we're not doing something stupid
-
-
- -
- - - - -
Commit:0d8ba8c2632e129fe7627f86d907c8b470c1bf20
Author:Pieter de Bie
Date:1 year, 1 month ago
-
Rename 'CachedChanges" to "StagedChanges" for greater consistency
-
-
- -
- - - - -
Commit:f9ff15cc6bf3c807425321581002f676985dd222
Author:Pieter de Bie
Date:1 year, 1 month ago
-
PBChangedFile: remove shouldBeDeleted boolean
-
We don't need this anymore
-
- -
- - - - -
Commit:8d729dae4cc8d3b564d149d6c9bb96922ee1bafa
Author:Pieter de Bie
Date:1 year, 6 months ago
-
CommitView: Don't change selection when refreshing
-
We used to read in a completely new array when refreshing -the index. The problem with this is that the selection -changes when reading in the new array. We avoid this -by changing the current array, rather than loading in -a completely new one.
-
- -
- - - - -
Commit:0975426f2f5119335c00768006b1ede0252ac448
Author:Pieter de Bie
Date:2 years, 7 months ago
-
CommitView: move index functions to separate controller
-
This merges functionality that was previously stored in the -combination of PBGitCommitController / PBChangedFile to a -dedicated controller, PBGitIndexController. -
-
- -
- - - - -
Commit:1d19bd64dfa83def18d5271c9afef9300ef0d65e
Author:Pieter de Bie
Date:2 years, 8 months ago
-
PBChangedFile: Don't use cat to read file contents
-
This changes PBChangedFile to read in files by using -NSString's stringWithContentsOfFile: method. - -It still uses the UTF8 encoding scheme so that we -can capture binary files. This should perhaps be loosened to -also allow other encodings. -
-
- -
- - - - -
Commit:472d36c7f970d9f3dbda3b9d7c8a7d51546bda56
Author:Pieter de Bie
Date:2 years, 8 months ago
-
CommitView: Add context menu to revert changes
-
-
- -
- - - - -
Commit:e659e63fc08ecd46cc1c26b6260126502ec656aa
Author:Pieter de Bie
Date:2 years, 8 months ago
-
CommitView: Add option to amend commits
-
-
- -
- - - - -
Commit:5010511bdb358ad376fd4668368bc5c12d9d8214
Author:Pieter de Bie
Date:2 years, 8 months ago
-
CommitView: Always use a single PBChangedFile object
-
This makes sure we don't add a double object to our array, -if a file has both cached and unstaged changes. -
-
- -
- - - - -
Commit:a0f248ef9f50a3af0efebdfb29c706bd97011a97
Author:Pieter de Bie
Date:2 years, 8 months ago
-
CommitView: Also show deleted files correctly
-
-
- -
- - - - -
Commit:001b6bf10eeaaf618971bc079e7415690c4c8d1a
Author:Pieter de Bie
Date:2 years, 9 months ago
-
CommitView: Handle new files better
-
This fixes the 'cat' command that was acting up and also shows -information when a file could not be displayed
-
- -
- - - - -
Commit:aafc284eb8fbd69acf40acfef07e25f409a87a18
Author:Pieter de Bie
Date:2 years, 9 months ago
-
ChangedFile: add a path separator to reset command
-
Sometimes a file could not be reset because it contained weird characters. - -This hopefully fixes it. -
-
- -
- - - - -
Commit:76e176e8b4ac59438340b129874ffbdfa7404ea3
Author:Pieter de Bie
Date:2 years, 9 months ago
-
Add staging and unstaging of files
-
-
- -
- - - - -
Commit:9b3909e7592d3c8648accb67642a2b57a441f128
Author:Pieter de Bie
Date:2 years, 9 months ago
-
CommitView: Add a status bar to the diff view
-
-
- -
- - - - -
Commit:44009b6f3e7e6fc5b54910c2b2a9a54b13f95a14
Author:Pieter de Bie
Date:2 years, 9 months ago
-
CommitView: use only one array for all files
-
-
- -
- - - - -
Commit:252796ee26ce733c4a6d3044e3142f9ee5df005e
Author:Pieter de Bie
Date:2 years, 9 months ago
-
CommitView: Show basic files
-
-
- - \ No newline at end of file diff --git a/html/views/source/index.html b/html/views/source/index.html new file mode 100644 index 000000000..356c1427e --- /dev/null +++ b/html/views/source/index.html @@ -0,0 +1,16 @@ + + + + + + + + + + + + +
+
+ + \ No newline at end of file diff --git a/html/views/source/source.css b/html/views/source/source.css new file mode 100644 index 000000000..e69de29bb diff --git a/html/views/source/source.js b/html/views/source/source.js new file mode 100644 index 000000000..2168e9e9f --- /dev/null +++ b/html/views/source/source.js @@ -0,0 +1,9 @@ +var showFile = function(txt) { + $("source").style.display = ""; + $("source").innerHTML="
"+txt+"
"; + + SyntaxHighlighter.defaults['toolbar'] = false; + SyntaxHighlighter.highlight(); + + return; +} diff --git a/libgit2 b/libgit2 deleted file mode 160000 index bda29d0f7..000000000 --- a/libgit2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bda29d0f7bc59a821b03c716562aef6ea3b5903a diff --git a/list_Template.png b/list_Template.png new file mode 100644 index 000000000..690ace16f Binary files /dev/null and b/list_Template.png differ diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 000000000..e9df72306 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +# untitled.sh +# GitX +# +# Created by Andre Berg on 19.10.09. +# Copyright 2009 Berg Media. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Installs GitX.app to $CUSTOM_INSTALL_DIR from Install.xcconfig +# Installs gitx to $CLI_CUSTOM_INSTALL_DIR from Install.xcconfig using gitx_askpasswd + +export SUDO_ASKPASS="$BUILT_PRODUCTS_DIR/gitx_askpasswd" +export GITX_ASKPASSWD_DIALOG_TITLE="Please enter sudo pass for Install" + +if [[ $BUILD_STYLE =~ "Install" ]]; then + if [[ $TARGET_NAME =~ "$PRODUCT_NAME" ]]; then + # install GitX + echo "Installing ${FULL_PRODUCT_NAME} to ${CUSTOM_INSTALL_DIR}... " + echo "(switch to build config other than Install to avoid)" + if [[ ! -d "$CUSTOM_INSTALL_DIR" ]]; then + echo "$CUSTOM_INSTALL_DIR doesn't exist. Will create it for you..." + sudo -A -E /bin/mkdir -p "${CUSTOM_INSTALL_DIR}" + fi + if [[ -e /opt/local/bin/rsync ]]; then + /opt/local/bin/rsync -rlHEptog --xattrs --acls "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" "$CUSTOM_INSTALL_DIR/" + else + /usr/bin/rsync -rlHEptog "$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME" "$CUSTOM_INSTALL_DIR/" + fi + elif [[ $TARGET_NAME =~ "cli tool" ]]; then + # install cli tool + echo "Installing gitx command line tool to ${CLI_CUSTOM_INSTALL_DIR}..." + echo "(switch to build config other than Install to avoid)" + if [[ ! -d "$CLI_CUSTOM_INSTALL_DIR" ]]; then + echo "$CLI_CUSTOM_INSTALL_DIR doesn't exist. Will create it for you..." + sudo -A -E /bin/mkdir -p "${CLI_CUSTOM_INSTALL_DIR}" + fi + if [[ -e /opt/local/bin/rsync ]]; then + sudo -A -E /opt/local/bin/rsync -rlHEptog --xattrs --acls "$BUILT_PRODUCTS_DIR/gitx" "$CLI_CUSTOM_INSTALL_DIR/" + else + sudo -A -E /usr/bin/rsync -rlHEptog "$BUILT_PRODUCTS_DIR/gitx" "$CLI_CUSTOM_INSTALL_DIR/" + fi + fi +else + echo '$BUILD_STYLE does not contain "Install"... nothing to copy' +fi \ No newline at end of file diff --git a/sidebar_Template.png b/sidebar_Template.png new file mode 100644 index 000000000..9326ad99b Binary files /dev/null and b/sidebar_Template.png differ diff --git a/source.css b/source.css new file mode 100644 index 000000000..e69de29bb diff --git a/sourceListAction.png b/sourceListAction.png new file mode 100644 index 000000000..9122fc17e Binary files /dev/null and b/sourceListAction.png differ diff --git a/sourceListActionOver.png b/sourceListActionOver.png new file mode 100644 index 000000000..70e0cb0c4 Binary files /dev/null and b/sourceListActionOver.png differ diff --git a/stash-icon.png b/stash-icon.png new file mode 100644 index 000000000..d861fb239 Binary files /dev/null and b/stash-icon.png differ diff --git a/submodule-empty.png b/submodule-empty.png new file mode 100644 index 000000000..c012e6110 Binary files /dev/null and b/submodule-empty.png differ diff --git a/submodule-matching-index.png b/submodule-matching-index.png new file mode 100644 index 000000000..42d25baf3 Binary files /dev/null and b/submodule-matching-index.png differ diff --git a/submodule-notmatching-index.png b/submodule-notmatching-index.png new file mode 100644 index 000000000..d5abd307c Binary files /dev/null and b/submodule-notmatching-index.png differ