A view that emits confetti 🎉
Simple collaboration from your desktop
The Git interface you've been missing all your life has finally arrived.
The source for https://gohugo.io/
A methodology for building high-quality iOS apps on a solid architecture
Democratizing WordPress.com legalese since 2014!
Swift based OAuth library for iOS
Swift package for a SwiftUI remote image view
PR closed git-up/GitUp
yes
pr closed time in 10 days
PR opened git-up/GitUp
yes
pr created time in 10 days
Pull request review commentgit-up/GitUp
- (void)_reloadDeltas { GCDiffPatch* patch = [self.repository makePatchForDiffDelta:delta isBinary:&isBinary error:&error]; if (patch) { XLOG_DEBUG_CHECK(!isBinary || patch.empty);- if (patch.empty) {++ BOOL isImage = [[NSImage alloc] initWithContentsOfFile:[self.repository absolutePathForFile:delta.canonicalPath]] != nil;
Sorted! bae1fc2d943165e92308ef3d57e030c3abd54e96
comment created time in 13 days
Pull request review commentgit-up/GitUp
- (void)_reloadDeltas { GCDiffPatch* patch = [self.repository makePatchForDiffDelta:delta isBinary:&isBinary error:&error]; if (patch) { XLOG_DEBUG_CHECK(!isBinary || patch.empty);- if (patch.empty) {++ BOOL isImage = [[NSImage alloc] initWithContentsOfFile:[self.repository absolutePathForFile:delta.canonicalPath]] != nil;
I think that should mostly be right, but to verify NSImageView can load it we probably should use NSImage.imageTypes to get the array of valid UTIs and then check conformance against those to see if we match any. I think kUTTypeImage type might be too generic.
comment created time in 14 days
Pull request review commentgit-up/GitUp
+#if !__has_feature(objc_arc)+#error This file requires ARC+#endif++#import "GIPrivate.h"+#import "GILaunchServicesLocator.h"+#import <QuartzCore/CATransaction.h>++#define kImageInset 10+#define kBorderWidth 8+#define kDividerWidth 2++@interface GIImageDiffView ()+@property(nonatomic, strong) NSPanGestureRecognizer* panGestureRecognizer;+@property(nonatomic, strong) NSClickGestureRecognizer* clickGestureRecognizer;+@property(nonatomic, strong) GCLiveRepository* repository;+@property(nonatomic, strong) NSImageView* oldImageView;+@property(nonatomic, strong) NSImageView* currentImageView;+@property(nonatomic, strong) CALayer* oldImageMaskLayer;+@property(nonatomic, strong) CALayer* currentImageMaskLayer;+@property(nonatomic, strong) CALayer* oldImageBorderLayer;+@property(nonatomic, strong) CALayer* currentImageBorderLayer;+@property(nonatomic, strong) NSView* dividerView;+@property(nonatomic, strong) CALayer* transparencyCheckerboardLayer;+@property(nonatomic, strong) NSColor* checkerboardColor;+@property(nonatomic) CGFloat percentage;+@end++@implementation GIImageDiffView+- (id)initWithRepository:(GCLiveRepository*)repository {+ self = [super initWithFrame:CGRectZero];+ self.repository = repository;+ _percentage = 0.5;+ [self setupView];+ return self;+}++- (void)setupView {+ self.wantsLayer = true;++ _oldImageBorderLayer = [[CALayer alloc] init];+ _currentImageBorderLayer = [[CALayer alloc] init];+ [self.layer addSublayer:_oldImageBorderLayer];+ [self.layer addSublayer:_currentImageBorderLayer];++ _transparencyCheckerboardLayer = [[CALayer alloc] init];+ NSBundle* bundle = NSBundle.gitUpKitBundle;+ NSImage* patternImage = [bundle imageForResource:@"background_pattern"];+ _checkerboardColor = [NSColor colorWithPatternImage:patternImage];+ _transparencyCheckerboardLayer.backgroundColor = _checkerboardColor.CGColor;+ [self.layer addSublayer:_transparencyCheckerboardLayer];++ _currentImageView = [[NSImageView alloc] init];+ _oldImageView = [[NSImageView alloc] init];+ [self addSubview:_currentImageView];+ [self addSubview:_oldImageView];++ _oldImageMaskLayer = [[CALayer alloc] init];+ _oldImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _oldImageView.wantsLayer = true;+ _oldImageView.layer.mask = _oldImageMaskLayer;++ _currentImageMaskLayer = [[CALayer alloc] init];+ _currentImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _currentImageView.wantsLayer = true;+ _currentImageView.layer.mask = _currentImageMaskLayer;++ _dividerView = [[NSView alloc] init];+ [self addSubview:_dividerView];++ _panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ _clickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ [self addGestureRecognizer:_panGestureRecognizer];+ [self addGestureRecognizer:_clickGestureRecognizer];+}++- (void)setDelta:(GCDiffDelta*)delta {+ if (delta != _delta) {+ _delta = delta;+ [self updateCurrentImage];+ [self updateOldImage];+ self.percentage = 0.5;+ }+}++- (void)setPercentage:(CGFloat)percentage {+ _percentage = percentage;+ [self setNeedsDisplay:true];+}++- (void)updateCurrentImage {+ NSError* error;+ NSString* newPath;+ if (_delta.newFile.SHA1 != nil) {+ newPath = [GILaunchServicesLocator.diffTemporaryDirectoryPath stringByAppendingPathComponent:_delta.newFile.SHA1];+ NSString* newExtension = _delta.newFile.path.pathExtension;+ if (newExtension.length) {+ newPath = [newPath stringByAppendingPathExtension:newExtension];+ }+ if (![[NSFileManager defaultManager] fileExistsAtPath:newPath]) {+ [self.repository exportBlobWithSHA1:_delta.newFile.SHA1 toPath:newPath error:&error];+ }+ } else {+ newPath = [self.repository absolutePathForFile:_delta.canonicalPath];+ }+ _currentImageView.image = [[NSImage alloc] initWithContentsOfFile:newPath];
With regards to separating out image loading and size calculations: Does that mean you would want to make the cells a static height?
Right now we load the new images on setDelta and then query their dimensions during the sizing calculations to make sure they aren't scaled improperly and the aspect ratios make sense.
So the only way I could think of to avoid this reliance on in-memory images would be to set an arbitrary height and then cram the images into that space whenever they are ready 🤔
comment created time in 15 days
Pull request review commentgit-up/GitUp
+#if !__has_feature(objc_arc)+#error This file requires ARC+#endif++#import "GIPrivate.h"+#import "GILaunchServicesLocator.h"+#import <QuartzCore/CATransaction.h>++#define kImageInset 10+#define kBorderWidth 8+#define kDividerWidth 2++@interface GIImageDiffView ()+@property(nonatomic, strong) NSPanGestureRecognizer* panGestureRecognizer;+@property(nonatomic, strong) NSClickGestureRecognizer* clickGestureRecognizer;+@property(nonatomic, strong) GCLiveRepository* repository;+@property(nonatomic, strong) NSImageView* oldImageView;+@property(nonatomic, strong) NSImageView* currentImageView;+@property(nonatomic, strong) CALayer* oldImageMaskLayer;+@property(nonatomic, strong) CALayer* currentImageMaskLayer;+@property(nonatomic, strong) CALayer* oldImageBorderLayer;+@property(nonatomic, strong) CALayer* currentImageBorderLayer;+@property(nonatomic, strong) NSView* dividerView;+@property(nonatomic, strong) CALayer* transparencyCheckerboardLayer;+@property(nonatomic, strong) NSColor* checkerboardColor;+@property(nonatomic) CGFloat percentage;+@end++@implementation GIImageDiffView+- (id)initWithRepository:(GCLiveRepository*)repository {+ self = [super initWithFrame:CGRectZero];+ self.repository = repository;+ _percentage = 0.5;+ [self setupView];+ return self;+}++- (void)setupView {+ self.wantsLayer = true;++ _oldImageBorderLayer = [[CALayer alloc] init];+ _currentImageBorderLayer = [[CALayer alloc] init];+ [self.layer addSublayer:_oldImageBorderLayer];+ [self.layer addSublayer:_currentImageBorderLayer];++ _transparencyCheckerboardLayer = [[CALayer alloc] init];+ NSBundle* bundle = NSBundle.gitUpKitBundle;+ NSImage* patternImage = [bundle imageForResource:@"background_pattern"];+ _checkerboardColor = [NSColor colorWithPatternImage:patternImage];+ _transparencyCheckerboardLayer.backgroundColor = _checkerboardColor.CGColor;+ [self.layer addSublayer:_transparencyCheckerboardLayer];++ _currentImageView = [[NSImageView alloc] init];+ _oldImageView = [[NSImageView alloc] init];+ [self addSubview:_currentImageView];+ [self addSubview:_oldImageView];++ _oldImageMaskLayer = [[CALayer alloc] init];+ _oldImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _oldImageView.wantsLayer = true;+ _oldImageView.layer.mask = _oldImageMaskLayer;++ _currentImageMaskLayer = [[CALayer alloc] init];+ _currentImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _currentImageView.wantsLayer = true;+ _currentImageView.layer.mask = _currentImageMaskLayer;++ _dividerView = [[NSView alloc] init];+ [self addSubview:_dividerView];++ _panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ _clickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ [self addGestureRecognizer:_panGestureRecognizer];+ [self addGestureRecognizer:_clickGestureRecognizer];+}++- (void)setDelta:(GCDiffDelta*)delta {+ if (delta != _delta) {+ _delta = delta;+ [self updateCurrentImage];+ [self updateOldImage];+ self.percentage = 0.5;+ }+}++- (void)setPercentage:(CGFloat)percentage {+ _percentage = percentage;+ [self setNeedsDisplay:true];+}++- (void)updateCurrentImage {+ NSError* error;+ NSString* newPath;+ if (_delta.newFile.SHA1 != nil) {+ newPath = [GILaunchServicesLocator.diffTemporaryDirectoryPath stringByAppendingPathComponent:_delta.newFile.SHA1];+ NSString* newExtension = _delta.newFile.path.pathExtension;+ if (newExtension.length) {+ newPath = [newPath stringByAppendingPathExtension:newExtension];+ }+ if (![[NSFileManager defaultManager] fileExistsAtPath:newPath]) {+ [self.repository exportBlobWithSHA1:_delta.newFile.SHA1 toPath:newPath error:&error];+ }+ } else {+ newPath = [self.repository absolutePathForFile:_delta.canonicalPath];+ }+ _currentImageView.image = [[NSImage alloc] initWithContentsOfFile:newPath];
Yeah, limiting the size in memory definitely sounds advisable! I took care of that in 991f88908737795da132a25a4a2fef40e01c0364. For now I simply used a somewhat arbitrary maximum image dimension of 4000 pixels, because it was easy to do and seemed like a reasonable limit. If you think we should change this value or even make it scale dynamically by screen size or something like that let me know 🙂
comment created time in 15 days
Pull request review commentgit-up/GitUp
- (void)_reloadDeltas { GCDiffPatch* patch = [self.repository makePatchForDiffDelta:delta isBinary:&isBinary error:&error]; if (patch) { XLOG_DEBUG_CHECK(!isBinary || patch.empty);- if (patch.empty) {++ BOOL isImage = [[NSImage alloc] initWithContentsOfFile:[self.repository absolutePathForFile:delta.canonicalPath]] != nil;
Great point! I switched it over to using UTIs, which should be very fast and still plenty reliable 🙂 (c4f52a4fbc19dd030341c6b220c7bf75d31b5216)
I'm not super familiar with memory management bridging for core foundation entities, though, so that part could definitely use a thorough look 😅 (the same goes for my other fix).
comment created time in 15 days
pull request commentgit-up/GitUp
Looking forward to this feature! Looks great!
comment created time in 20 days
pull request commentgit-up/GitUp
To use libgit2 as generated project, we have to solve several tasks.
- Add an option ( custom file path ) to a library.
- Figure out how to add xcframeworks to a library.
- Fix AddressSanitizer issue.
- Fix linking issues if needed. ( Security.framework is not linked well ).
comment created time in a month
issue commentgit-up/GitUp
App is hang when open/commit/stage/discard in large repository
levantAJcomment created time in a month
issue commentgit-up/GitUp
App is hang when open/commit/stage/discard in large repository
@levantAJ https://kb.parallels.com/en/123078
comment created time in a month
issue commentgit-up/GitUp
App is hang when open/commit/stage/discard in large repository
I can give you an example how to reproduce it.
- Run ./update-Xcode.sh script at libgit2.
- Add generated libgit2.xcodeproj file to repository ( ignore .gitignore ) ( git add ...
- Try to select this file in commit view.
comment created time in a month
issue openedgit-up/GitUp
I suggest having support for multiple identities, which can include, for example:
- Name
- Email address
- ssh key
So, for example, each repository could be configured to have a committer identity which will be used. A similar feature in Tower app: https://www.git-tower.com/help/guides/working-copy/user-profiles/mac
created time in a month
pull request commentgit-up/GitUp
@lucasderraugh Could you test it?
I'm not sure how it would be possible to build this library with all these CMakeLists.
I guess the most ( and the one? ) proper way is to duplicate all settings from generated xcodeproj.
But it has something strange with object files.
Related Cmake issue.
comment created time in a month
PR opened git-up/GitUp
- [x] libgit2 v1.1.0 has been updated.
TODO
- [ ] submodule commit has been updated.
- [x] Application compiles.
- [ ] Application runs.
- [ ] Application works well.
pr created time in a month
issue commentgit-up/GitUp
Uncaught exception on startup (macOS 10.11, GitUp release v1.2)
Is it possible to increase a deployment target number to 10.11?
Yes, but it's a bit off topic for this discussion. I think I'll make a formal document for when we bump versions. It's a bit confusing what's the currently supported OS.
comment created time in a month
issue commentgit-up/GitUp
Uncaught exception on startup (macOS 10.11, GitUp release v1.2)
Is it possible to increase a deployment target number to 10.11?
comment created time in a month
pull request commentgit-up/GitUp
[Feature] Quick View: Show history of file
I did it! Carefully rebase all commits onto old master and then merge current master.
comment created time in a month
pull request commentgit-up/GitUp
[Feature] Quick View: Show history of file
@lucasderraugh
I have a strange bug with this GitUpKit.xcodeproj file.
- Choose all changes from master.
- Build project.
Result
../GitUp/GitUp/GitUp.xcodeproj This Copy Files build phase contains a reference to a missing file 'GitUpKit.framework'.
comment created time in a month
pull request commentgit-up/GitUp
[Feature] Quick View: Show history of file
@lucasderraugh Sure. It's strange, I try to merge master in it and beachball has appeared. Maybe it is because of a lot of binary changes( pictures and deleted/added frameworks ). GitUp is hanging for a bit.
comment created time in a month
pull request commentgit-up/GitUp
[Feature] Quick View: Show history of file
@lolgear Can you rebase this branch so we can try to get it in for next release?
comment created time in a month
Pull request review commentgit-up/GitUp
+#if !__has_feature(objc_arc)+#error This file requires ARC+#endif++#import "GIPrivate.h"+#import "GILaunchServicesLocator.h"+#import <QuartzCore/CATransaction.h>++#define kImageInset 10+#define kBorderWidth 8+#define kDividerWidth 2++@interface GIImageDiffView ()+@property(nonatomic, strong) NSPanGestureRecognizer* panGestureRecognizer;+@property(nonatomic, strong) NSClickGestureRecognizer* clickGestureRecognizer;+@property(nonatomic, strong) GCLiveRepository* repository;+@property(nonatomic, strong) NSImageView* oldImageView;+@property(nonatomic, strong) NSImageView* currentImageView;+@property(nonatomic, strong) CALayer* oldImageMaskLayer;+@property(nonatomic, strong) CALayer* currentImageMaskLayer;+@property(nonatomic, strong) CALayer* oldImageBorderLayer;+@property(nonatomic, strong) CALayer* currentImageBorderLayer;+@property(nonatomic, strong) NSView* dividerView;+@property(nonatomic, strong) CALayer* transparencyCheckerboardLayer;+@property(nonatomic, strong) NSColor* checkerboardColor;+@property(nonatomic) CGFloat percentage;+@end++@implementation GIImageDiffView+- (id)initWithRepository:(GCLiveRepository*)repository {+ self = [super initWithFrame:CGRectZero];+ self.repository = repository;+ _percentage = 0.5;+ [self setupView];+ return self;+}++- (void)setupView {+ self.wantsLayer = true;++ _oldImageBorderLayer = [[CALayer alloc] init];+ _currentImageBorderLayer = [[CALayer alloc] init];+ [self.layer addSublayer:_oldImageBorderLayer];+ [self.layer addSublayer:_currentImageBorderLayer];++ _transparencyCheckerboardLayer = [[CALayer alloc] init];+ NSBundle* bundle = NSBundle.gitUpKitBundle;+ NSImage* patternImage = [bundle imageForResource:@"background_pattern"];+ _checkerboardColor = [NSColor colorWithPatternImage:patternImage];+ _transparencyCheckerboardLayer.backgroundColor = _checkerboardColor.CGColor;+ [self.layer addSublayer:_transparencyCheckerboardLayer];++ _currentImageView = [[NSImageView alloc] init];+ _oldImageView = [[NSImageView alloc] init];+ [self addSubview:_currentImageView];+ [self addSubview:_oldImageView];++ _oldImageMaskLayer = [[CALayer alloc] init];+ _oldImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _oldImageView.wantsLayer = true;+ _oldImageView.layer.mask = _oldImageMaskLayer;++ _currentImageMaskLayer = [[CALayer alloc] init];+ _currentImageMaskLayer.backgroundColor = NSColor.blackColor.CGColor;+ _currentImageView.wantsLayer = true;+ _currentImageView.layer.mask = _currentImageMaskLayer;++ _dividerView = [[NSView alloc] init];+ [self addSubview:_dividerView];++ _panGestureRecognizer = [[NSPanGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ _clickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(didMoveSplit:)];+ [self addGestureRecognizer:_panGestureRecognizer];+ [self addGestureRecognizer:_clickGestureRecognizer];+}++- (void)setDelta:(GCDiffDelta*)delta {+ if (delta != _delta) {+ _delta = delta;+ [self updateCurrentImage];+ [self updateOldImage];+ self.percentage = 0.5;+ }+}++- (void)setPercentage:(CGFloat)percentage {+ _percentage = percentage;+ [self setNeedsDisplay:true];+}++- (void)updateCurrentImage {+ NSError* error;+ NSString* newPath;+ if (_delta.newFile.SHA1 != nil) {+ newPath = [GILaunchServicesLocator.diffTemporaryDirectoryPath stringByAppendingPathComponent:_delta.newFile.SHA1];+ NSString* newExtension = _delta.newFile.path.pathExtension;+ if (newExtension.length) {+ newPath = [newPath stringByAppendingPathExtension:newExtension];+ }+ if (![[NSFileManager defaultManager] fileExistsAtPath:newPath]) {+ [self.repository exportBlobWithSHA1:_delta.newFile.SHA1 toPath:newPath error:&error];+ }+ } else {+ newPath = [self.repository absolutePathForFile:_delta.canonicalPath];+ }+ _currentImageView.image = [[NSImage alloc] initWithContentsOfFile:newPath];
I'm a bit concerned about loading in the file this way in cases where the asset is rather large. For most cases we're probably not dealing with giant assets, but if you do this is going to grind to a halt. We should probably generate a thumbnail of a max size so we cap the load time. Another optimization we should probably have is to separate out the image loading and size calculations. The table view needs to know size (because we don't use automatic height adjustments yet, unfortunately) and the size calculation should be as fast as possible.
comment created time in a month
Pull request review commentgit-up/GitUp
- (void)_reloadDeltas { GCDiffPatch* patch = [self.repository makePatchForDiffDelta:delta isBinary:&isBinary error:&error]; if (patch) { XLOG_DEBUG_CHECK(!isBinary || patch.empty);- if (patch.empty) {++ BOOL isImage = [[NSImage alloc] initWithContentsOfFile:[self.repository absolutePathForFile:delta.canonicalPath]] != nil;
I think we need a lighter weight approach for determining if a path may be an image. If we have a lot of images and large images then we're going to load them all into memory up front and that could be very slow.
comment created time in a month
issue commentgit-up/GitUp
App is hang when open/commit/stage/discard in large repository
Thanks @lucasderraugh Could you guide me on how to capture a spin trace of the app?
comment created time in a month
issue commentgit-up/GitUp
Uncaught exception on startup (macOS 10.11, GitUp release v1.2)
Actually pretty easy to address this issue for backwards compatibility. For some reason the API doesn't warn about using it pre 10.14 but it would appear that it's not available before that release.
@property (nullable, strong) NSAppearance *appearance API_AVAILABLE(macos(10.14));
comment created time in a month
issue commentgit-up/GitUp
App is hang when open/commit/stage/discard in large repository
Definitely can, it's probably one of the known perf issues we have in large repositories. If you can capture a spin trace of the app when the app hangs and attach that here we can trace back what's taking so long.
comment created time in a month
issue closedgit-up/GitUp
I need "Reverse Hunk" Button like SourceTree.
I feel "Reverse Hunk" Button really useful in SourceTree.

I love the beautiful UI of GitUp more than SourceTree.
Do you have a plan to implement "Reverse Hunk" Button?
closed time in a month
LittleWat