diff --git a/GitUp/Application/Base.lproj/MainMenu.xib b/GitUp/Application/Base.lproj/MainMenu.xib index 528efb47..3630edc0 100644 --- a/GitUp/Application/Base.lproj/MainMenu.xib +++ b/GitUp/Application/Base.lproj/MainMenu.xib @@ -292,6 +292,12 @@ + + + + + + diff --git a/GitUpKit/Views/GIMapViewController+Operations.h b/GitUpKit/Views/GIMapViewController+Operations.h index 1b6df0c9..337f6060 100644 --- a/GitUpKit/Views/GIMapViewController+Operations.h +++ b/GitUpKit/Views/GIMapViewController+Operations.h @@ -59,6 +59,7 @@ - (void)pushAllLocalBranchesToAllRemotes; - (void)pushTag:(GCHistoryTag*)tag toRemote:(GCRemote*)remote; - (void)pushAllTagsToAllRemotes; +- (void)pushTagsToAllRemotes:(NSArray*)tags; - (void)pullLocalBranchFromUpstream:(GCHistoryLocalBranch*)branch; @end diff --git a/GitUpKit/Views/GIMapViewController+Operations.m b/GitUpKit/Views/GIMapViewController+Operations.m index 3af3f45f..95f10733 100644 --- a/GitUpKit/Views/GIMapViewController+Operations.m +++ b/GitUpKit/Views/GIMapViewController+Operations.m @@ -26,6 +26,7 @@ #define kUserDefaultsPrefix @"GIMapViewController_" #define kUserDefaultsKey_SkipPushTagWarning kUserDefaultsPrefix "SkipPushTagWarning" +#define kUserDefaultsKey_SkipPushCurrentCommitTagsWarning kUserDefaultsPrefix "SkipPushCurrentCommitTagsWarning" #define kUserDefaultsKey_SkipFetchRemoteBranchWarning kUserDefaultsPrefix "SkipFetchRemoteBranchWarning" #define kUserDefaultsKey_SkipPullBranchWarning kUserDefaultsPrefix "SkipPullBranchWarning" #define kUserDefaultsKey_SkipPushBranchWarning kUserDefaultsPrefix "SkipPushBranchWarning" @@ -971,6 +972,52 @@ - (void)pushAllTagsToAllRemotes { } } +// IMPORTANT: See comment above regarding tags being force-pushed +- (void)pushTagsToAllRemotes:(NSArray*)tags { + if (!tags.count) { + return; + } + + NSString* names = [[tags valueForKey:@"name"] componentsJoinedByString:@", "]; + [self confirmUserActionWithAlertType:kGIAlertType_Caution + title:[NSString stringWithFormat:NSLocalizedString(@"Are you sure you want to push the current commit tags (%@) to all remotes?", nil), names] + message:NSLocalizedString(@"This action cannot be undone.", nil) + button:NSLocalizedString(@"Push Tags", nil) + suppressionUserDefaultKey:kUserDefaultsKey_SkipPushCurrentCommitTagsWarning + block:^{ + NSError* localError; + NSArray* remotes = [self.repository listRemotes:&localError]; + if (remotes == nil) { + [self presentError:localError]; + return; + } + if (!remotes.count) { + [self.windowController showOverlayWithStyle:kGIOverlayStyle_Warning message:NSLocalizedString(@"There are no remotes to push to!", nil)]; + return; + } + + [self.repository performOperationInBackgroundWithReason:nil + argument:nil + usingOperationBlock:^BOOL(GCRepository* repository, NSError** error) { + for (GCRemote* remote in remotes) { + for (GCTag* tag in tags) { + if (![repository pushTag:tag toRemote:remote force:YES error:error]) { + return NO; + } + } + } + return YES; + } + completionBlock:^(BOOL success, NSError* error) { + if (success) { + [self.windowController showOverlayWithStyle:kGIOverlayStyle_Informational message:NSLocalizedString(@"The current commit tags were pushed to all remotes successfully!", nil)]; + } else { + [self presentError:error]; + } + }]; + }]; +} + #pragma mark - Remote Delete - (void)_deleteRemoteBranchFromRemote:(GCHistoryRemoteBranch*)branch { diff --git a/GitUpKit/Views/GIMapViewController.h b/GitUpKit/Views/GIMapViewController.h index 589fda74..df767e4d 100644 --- a/GitUpKit/Views/GIMapViewController.h +++ b/GitUpKit/Views/GIMapViewController.h @@ -55,4 +55,5 @@ - (IBAction)pushAllTags:(id)sender; - (IBAction)pullCurrentBranch:(id)sender; - (IBAction)pushCurrentBranch:(id)sender; +- (IBAction)pushCurrentCommitTags:(id)sender; @end diff --git a/GitUpKit/Views/GIMapViewController.m b/GitUpKit/Views/GIMapViewController.m index 69efaed9..dbfdf716 100644 --- a/GitUpKit/Views/GIMapViewController.m +++ b/GitUpKit/Views/GIMapViewController.m @@ -638,6 +638,10 @@ - (BOOL)validateUserInterfaceItem:(id)item { if (item.action == @selector(pushCurrentBranch:)) { return !editingDisabled && self.repository.history.HEADBranch; } + if (item.action == @selector(pushCurrentCommitTags:)) { + GCHistoryCommit* currentCommit = _graphView.selectedCommit ?: self.repository.history.HEADCommit; + return !editingDisabled && currentCommit.tags.count > 0; + } GCHistoryCommit* commit = _graphView.selectedCommit; if (commit == nil) { @@ -793,6 +797,11 @@ - (IBAction)pushCurrentBranch:(id)sender { } } +- (IBAction)pushCurrentCommitTags:(id)sender { + GCHistoryCommit* commit = _graphView.selectedCommit ?: self.repository.history.HEADCommit; + [self pushTagsToAllRemotes:commit.tags]; +} + #pragma mark - Contextual Menu Actions - (IBAction)quickViewSelectedCommit:(id)sender {