2020-09-30 00:27:23 +02:00
package gui
import (
"fmt"
"os"
2020-09-30 13:12:03 +02:00
"path/filepath"
"strings"
2020-09-30 00:27:23 +02:00
"github.com/jesseduffield/lazygit/pkg/commands/models"
2021-07-27 15:00:37 +02:00
"github.com/jesseduffield/lazygit/pkg/gui/style"
2020-09-30 00:27:23 +02:00
)
func ( gui * Gui ) getSelectedSubmodule ( ) * models . SubmoduleConfig {
selectedLine := gui . State . Panels . Submodules . SelectedLineIdx
if selectedLine == - 1 || len ( gui . State . Submodules ) == 0 {
return nil
}
return gui . State . Submodules [ selectedLine ]
}
func ( gui * Gui ) handleSubmoduleSelect ( ) error {
var task updateTask
submodule := gui . getSelectedSubmodule ( )
if submodule == nil {
2021-04-04 15:51:59 +02:00
task = NewRenderStringTask ( "No submodules" )
2020-09-30 00:27:23 +02:00
} else {
2020-10-01 00:18:16 +02:00
prefix := fmt . Sprintf (
"Name: %s\nPath: %s\nUrl: %s\n\n" ,
2021-07-27 15:00:37 +02:00
style . FgGreen . Sprint ( submodule . Name ) ,
style . FgYellow . Sprint ( submodule . Path ) ,
style . FgCyan . Sprint ( submodule . Url ) ,
2020-09-30 00:27:23 +02:00
)
2020-10-01 00:18:16 +02:00
file := gui . fileForSubmodule ( submodule )
if file == nil {
2021-04-04 15:51:59 +02:00
task = NewRenderStringTask ( prefix )
2020-10-01 00:18:16 +02:00
} else {
2021-05-28 12:02:19 +02:00
cmdStr := gui . GitCommand . WorktreeFileDiffCmdStr ( file , false , ! file . HasUnstagedChanges && file . HasStagedChanges , gui . State . IgnoreWhitespaceInDiffView )
2020-10-01 00:18:16 +02:00
cmd := gui . OSCommand . ExecutableFromString ( cmdStr )
2021-04-04 15:51:59 +02:00
task = NewRunCommandTaskWithPrefix ( cmd , prefix )
2020-10-01 00:18:16 +02:00
}
2020-09-30 00:27:23 +02:00
}
return gui . refreshMainViews ( refreshMainOpts {
main : & viewUpdateOpts {
title : "Submodule" ,
task : task ,
} ,
} )
}
2020-10-01 00:18:16 +02:00
func ( gui * Gui ) refreshStateSubmoduleConfigs ( ) error {
configs , err := gui . GitCommand . GetSubmoduleConfigs ( )
if err != nil {
return err
2020-09-30 00:27:23 +02:00
}
2020-10-01 00:18:16 +02:00
gui . State . Submodules = configs
return nil
}
func ( gui * Gui ) handleSubmoduleEnter ( submodule * models . SubmoduleConfig ) error {
2020-09-30 00:27:23 +02:00
return gui . enterSubmodule ( submodule )
}
func ( gui * Gui ) enterSubmodule ( submodule * models . SubmoduleConfig ) error {
wd , err := os . Getwd ( )
if err != nil {
return err
}
2021-04-03 04:43:43 +02:00
gui . RepoPathStack = append ( gui . RepoPathStack , wd )
2020-09-30 00:27:23 +02:00
2021-04-05 05:22:03 +02:00
return gui . dispatchSwitchToRepo ( submodule . Path , true )
2020-09-30 00:27:23 +02:00
}
2020-10-01 01:04:09 +02:00
func ( gui * Gui ) removeSubmodule ( submodule * models . SubmoduleConfig ) error {
2020-09-30 01:06:11 +02:00
return gui . ask ( askOpts {
2020-10-04 02:00:48 +02:00
title : gui . Tr . RemoveSubmodule ,
prompt : fmt . Sprintf ( gui . Tr . RemoveSubmodulePrompt , submodule . Name ) ,
2020-09-30 01:06:11 +02:00
handleConfirm : func ( ) error {
2021-04-11 11:35:42 +02:00
if err := gui . GitCommand . WithSpan ( gui . Tr . Spans . RemoveSubmodule ) . SubmoduleDelete ( submodule ) ; err != nil {
2020-09-30 13:12:03 +02:00
return gui . surfaceError ( err )
2020-09-30 01:06:11 +02:00
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES , FILES } } )
2020-09-30 01:06:11 +02:00
} ,
} )
}
2020-10-01 00:18:16 +02:00
func ( gui * Gui ) handleResetSubmodule ( submodule * models . SubmoduleConfig ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcResettingSubmoduleStatus , func ( ) error {
2020-09-30 01:06:11 +02:00
return gui . resetSubmodule ( submodule )
} )
}
func ( gui * Gui ) fileForSubmodule ( submodule * models . SubmoduleConfig ) * models . File {
2021-03-31 14:26:53 +02:00
for _ , file := range gui . State . FileManager . GetAllFiles ( ) {
2020-09-30 01:06:11 +02:00
if file . IsSubmodule ( [ ] * models . SubmoduleConfig { submodule } ) {
return file
}
}
return nil
}
func ( gui * Gui ) resetSubmodule ( submodule * models . SubmoduleConfig ) error {
2021-04-11 11:35:42 +02:00
gitCommand := gui . GitCommand . WithSpan ( gui . Tr . Spans . ResetSubmodule )
2021-04-10 08:01:46 +02:00
2020-09-30 01:06:11 +02:00
file := gui . fileForSubmodule ( submodule )
if file != nil {
2021-04-10 08:01:46 +02:00
if err := gitCommand . UnStageFile ( file . Names ( ) , file . Tracked ) ; err != nil {
2020-09-30 01:06:11 +02:00
return gui . surfaceError ( err )
}
}
2021-04-10 08:01:46 +02:00
if err := gitCommand . SubmoduleStash ( submodule ) ; err != nil {
2020-09-30 01:06:11 +02:00
return gui . surfaceError ( err )
}
2021-04-10 08:01:46 +02:00
if err := gitCommand . SubmoduleReset ( submodule ) ; err != nil {
2020-09-30 01:06:11 +02:00
return gui . surfaceError ( err )
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { mode : ASYNC , scope : [ ] RefreshableView { FILES , SUBMODULES } } )
2020-09-30 01:06:11 +02:00
}
2020-09-30 13:12:03 +02:00
func ( gui * Gui ) handleAddSubmodule ( ) error {
2020-11-28 04:35:58 +02:00
return gui . prompt ( promptOpts {
title : gui . Tr . LcNewSubmoduleUrl ,
handleConfirm : func ( submoduleUrl string ) error {
nameSuggestion := filepath . Base ( strings . TrimSuffix ( submoduleUrl , filepath . Ext ( submoduleUrl ) ) )
return gui . prompt ( promptOpts {
title : gui . Tr . LcNewSubmoduleName ,
initialContent : nameSuggestion ,
handleConfirm : func ( submoduleName string ) error {
return gui . prompt ( promptOpts {
title : gui . Tr . LcNewSubmodulePath ,
initialContent : submoduleName ,
handleConfirm : func ( submodulePath string ) error {
return gui . WithWaitingStatus ( gui . Tr . LcAddingSubmoduleStatus , func ( ) error {
2021-04-11 11:35:42 +02:00
err := gui . GitCommand . WithSpan ( gui . Tr . Spans . AddSubmodule ) . SubmoduleAdd ( submoduleName , submodulePath , submoduleUrl )
2020-11-28 04:35:58 +02:00
gui . handleCredentialsPopup ( err )
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-11-28 04:35:58 +02:00
} )
} ,
} )
} ,
2020-09-30 14:05:34 +02:00
} )
2020-11-28 04:35:58 +02:00
} ,
2020-09-30 14:05:34 +02:00
} )
2020-11-28 04:35:58 +02:00
2020-09-30 14:05:34 +02:00
}
2020-10-01 00:18:16 +02:00
func ( gui * Gui ) handleEditSubmoduleUrl ( submodule * models . SubmoduleConfig ) error {
2020-11-28 04:35:58 +02:00
return gui . prompt ( promptOpts {
title : fmt . Sprintf ( gui . Tr . LcUpdateSubmoduleUrl , submodule . Name ) ,
initialContent : submodule . Url ,
handleConfirm : func ( newUrl string ) error {
return gui . WithWaitingStatus ( gui . Tr . LcUpdatingSubmoduleUrlStatus , func ( ) error {
2021-04-11 11:35:42 +02:00
err := gui . GitCommand . WithSpan ( gui . Tr . Spans . UpdateSubmoduleUrl ) . SubmoduleUpdateUrl ( submodule . Name , submodule . Path , newUrl )
2020-11-28 04:35:58 +02:00
gui . handleCredentialsPopup ( err )
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-11-28 04:35:58 +02:00
} )
} ,
2020-09-30 13:12:03 +02:00
} )
}
2020-09-30 00:27:23 +02:00
2020-10-01 00:18:16 +02:00
func ( gui * Gui ) handleSubmoduleInit ( submodule * models . SubmoduleConfig ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcInitializingSubmoduleStatus , func ( ) error {
2021-04-11 11:35:42 +02:00
err := gui . GitCommand . WithSpan ( gui . Tr . Spans . InitialiseSubmodule ) . SubmoduleInit ( submodule . Path )
2020-10-01 00:18:16 +02:00
gui . handleCredentialsPopup ( err )
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 00:18:16 +02:00
} )
}
2021-04-02 10:20:40 +02:00
func ( gui * Gui ) forSubmodule ( callback func ( * models . SubmoduleConfig ) error ) func ( ) error {
return func ( ) error {
submodule := gui . getSelectedSubmodule ( )
if submodule == nil {
return nil
}
2020-10-01 00:18:16 +02:00
2021-04-02 10:20:40 +02:00
return callback ( submodule )
}
2020-10-01 00:18:16 +02:00
}
2020-10-01 01:04:09 +02:00
func ( gui * Gui ) handleResetRemoveSubmodule ( submodule * models . SubmoduleConfig ) error {
menuItems := [ ] * menuItem {
{
2020-10-04 02:00:48 +02:00
displayString : gui . Tr . LcSubmoduleStashAndReset ,
2020-10-01 01:04:09 +02:00
onPress : func ( ) error {
return gui . resetSubmodule ( submodule )
} ,
} ,
{
2020-10-04 02:00:48 +02:00
displayString : gui . Tr . LcRemoveSubmodule ,
2020-10-01 01:04:09 +02:00
onPress : func ( ) error {
return gui . removeSubmodule ( submodule )
} ,
} ,
}
return gui . createMenu ( submodule . Name , menuItems , createMenuOptions { showCancel : true } )
}
2020-10-01 14:13:32 +02:00
func ( gui * Gui ) handleBulkSubmoduleActionsMenu ( ) error {
menuItems := [ ] * menuItem {
{
2021-07-27 15:00:37 +02:00
displayStrings : [ ] string { gui . Tr . LcBulkInitSubmodules , style . FgGreen . Sprint ( gui . GitCommand . SubmoduleBulkInitCmdStr ( ) ) } ,
2020-10-01 14:13:32 +02:00
onPress : func ( ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcRunningCommand , func ( ) error {
2021-04-11 11:35:42 +02:00
if err := gui . OSCommand . WithSpan ( gui . Tr . Spans . BulkInitialiseSubmodules ) . RunCommand ( gui . GitCommand . SubmoduleBulkInitCmdStr ( ) ) ; err != nil {
2020-10-01 14:13:32 +02:00
return gui . surfaceError ( err )
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 14:13:32 +02:00
} )
} ,
} ,
{
2021-07-27 15:00:37 +02:00
displayStrings : [ ] string { gui . Tr . LcBulkUpdateSubmodules , style . FgYellow . Sprint ( gui . GitCommand . SubmoduleBulkUpdateCmdStr ( ) ) } ,
2020-10-01 14:13:32 +02:00
onPress : func ( ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcRunningCommand , func ( ) error {
2021-04-11 11:35:42 +02:00
if err := gui . OSCommand . WithSpan ( gui . Tr . Spans . BulkUpdateSubmodules ) . RunCommand ( gui . GitCommand . SubmoduleBulkUpdateCmdStr ( ) ) ; err != nil {
2020-10-01 14:13:32 +02:00
return gui . surfaceError ( err )
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 14:13:32 +02:00
} )
} ,
} ,
{
2021-07-27 15:00:37 +02:00
displayStrings : [ ] string { gui . Tr . LcSubmoduleStashAndReset , style . FgRed . Sprintf ( "git stash in each submodule && %s" , gui . GitCommand . SubmoduleForceBulkUpdateCmdStr ( ) ) } ,
2020-10-01 14:13:32 +02:00
onPress : func ( ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcRunningCommand , func ( ) error {
2021-04-11 11:35:42 +02:00
if err := gui . GitCommand . WithSpan ( gui . Tr . Spans . BulkStashAndResetSubmodules ) . ResetSubmodules ( gui . State . Submodules ) ; err != nil {
2020-10-01 14:13:32 +02:00
return gui . surfaceError ( err )
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 14:13:32 +02:00
} )
} ,
} ,
{
2021-07-27 15:00:37 +02:00
displayStrings : [ ] string { gui . Tr . LcBulkDeinitSubmodules , style . FgRed . Sprint ( gui . GitCommand . SubmoduleBulkDeinitCmdStr ( ) ) } ,
2020-10-01 14:13:32 +02:00
onPress : func ( ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcRunningCommand , func ( ) error {
2021-04-11 11:35:42 +02:00
if err := gui . OSCommand . WithSpan ( gui . Tr . Spans . BulkDeinitialiseSubmodules ) . RunCommand ( gui . GitCommand . SubmoduleBulkDeinitCmdStr ( ) ) ; err != nil {
2020-10-01 14:13:32 +02:00
return gui . surfaceError ( err )
}
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 14:13:32 +02:00
} )
} ,
} ,
}
2020-10-04 02:00:48 +02:00
return gui . createMenu ( gui . Tr . LcBulkSubmoduleOptions , menuItems , createMenuOptions { showCancel : true } )
2020-10-01 14:13:32 +02:00
}
2020-10-01 01:04:09 +02:00
func ( gui * Gui ) handleUpdateSubmodule ( submodule * models . SubmoduleConfig ) error {
2020-10-04 02:00:48 +02:00
return gui . WithWaitingStatus ( gui . Tr . LcUpdatingSubmoduleStatus , func ( ) error {
2021-04-11 11:35:42 +02:00
err := gui . GitCommand . WithSpan ( gui . Tr . Spans . UpdateSubmodule ) . SubmoduleUpdate ( submodule . Path )
2020-10-01 01:04:09 +02:00
gui . handleCredentialsPopup ( err )
2021-03-31 14:55:06 +02:00
return gui . refreshSidePanels ( refreshOptions { scope : [ ] RefreshableView { SUBMODULES } } )
2020-10-01 01:04:09 +02:00
} )
}