mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-06-08 23:56:15 +02:00
Add more demos (#2927)
This commit is contained in:
commit
70e668bfcf
21
README.md
21
README.md
@ -129,6 +129,27 @@ Learn more in the [Rebase magic Youtube tutorial](https://youtu.be/4XaToVut_hs).
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
### Rebase from marked base commit
|
||||||
|
|
||||||
|
Say you're on a feature branch that was itself branched off of the develop branch, and you've decided you'd rather be branching off the master branch. You need a way to rebase only the commits from your feature branch. In this demo we check to see which was the last commit on the develop branch, then press `shift+b` to mark that commit as our base commit, then press `r` on the master branch to rebase onto it, only bringing across the commits from our feature branch. Then we push our changes with `shift+p`.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Undo
|
||||||
|
|
||||||
|
You can undo the last action by pressing 'z' and redo with `ctrl+z`. Here we drop a couple of commits and then undo the actions.
|
||||||
|
Undo uses the reflog which is specific to commits and branches so we can't undo changes to the working tree or stash.
|
||||||
|
|
||||||
|
[More info](/docs/Undoing.md)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### Commit graph
|
||||||
|
|
||||||
|
When viewing the commit graph in an enlarged window (use `+` and `_` to cycle window sizes), the commit graph is shown. Colours correspond to the commit authors, and as you navigate down the graph, the parent commits of the selected commit are highlighted.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
## Tutorials
|
## Tutorials
|
||||||
|
|
||||||
[<img src="https://i.imgur.com/sVEktDn.png">](https://youtu.be/CPLdltN7wgE)
|
[<img src="https://i.imgur.com/sVEktDn.png">](https://youtu.be/CPLdltN7wgE)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# Undo/Redo in lazygit
|
# Undo/Redo in lazygit
|
||||||
|
|
||||||

|
You can undo the last action by pressing 'z' and redo with `ctrl+z`. Here we drop a couple of commits and then undo the actions.
|
||||||
|
Undo uses the reflog which is specific to commits and branches so we can't undo changes to the working tree or stash.
|
||||||
|
|
||||||
## Keybindings:
|

|
||||||
'z' to undo, 'ctrl+z' to redo
|
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
|||||||
}
|
}
|
||||||
err = self.CheckMergeOrRebase(err)
|
err = self.CheckMergeOrRebase(err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
self.c.Modes().MarkedBaseCommit.Reset()
|
return self.ResetMarkedBaseCommit()
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
@ -257,7 +257,9 @@ func (self *MergeAndRebaseHelper) RebaseOntoRef(ref string) error {
|
|||||||
if err = self.CheckMergeOrRebase(err); err != nil {
|
if err = self.CheckMergeOrRebase(err); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.c.Modes().MarkedBaseCommit.Reset()
|
if err = self.ResetMarkedBaseCommit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return self.c.PushContext(self.c.Contexts().LocalCommits)
|
return self.c.PushContext(self.c.Contexts().LocalCommits)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -210,3 +210,288 @@ var RandomFiles = []RandomFile{
|
|||||||
{Name: `seo/alt_text2.go`, Content: `package seo`},
|
{Name: `seo/alt_text2.go`, Content: `package seo`},
|
||||||
{Name: `moderation/comment_moderation2.go`, Content: `package moderation`},
|
{Name: `moderation/comment_moderation2.go`, Content: `package moderation`},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var RandomFileContents = []string{
|
||||||
|
`package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/format"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
code := generateCode()
|
||||||
|
|
||||||
|
formattedCode, err := format.Source(code)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile("test_list.go", formattedCode, 0o644); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/generics/set"
|
||||||
|
"github.com/jesseduffield/lazycore/pkg/utils"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTests() []*components.IntegrationTest {
|
||||||
|
// first we ensure that each test in this directory has actually been added to the above list.
|
||||||
|
testCount := 0
|
||||||
|
|
||||||
|
testNamesSet := set.NewFromSlice(lo.Map(
|
||||||
|
tests,
|
||||||
|
func(test *components.IntegrationTest, _ int) string {
|
||||||
|
return test.Name()
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/git_commands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IntegrationTest describes an integration test that will be run against the lazygit gui.
|
||||||
|
|
||||||
|
// our unit tests will use this description to avoid a panic caused by attempting
|
||||||
|
// to get the test's name via it's file's path.
|
||||||
|
const unitTestDescription = "test test"
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultWidth = 100
|
||||||
|
defaultHeight = 100
|
||||||
|
)
|
||||||
|
`,
|
||||||
|
`package components
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/atotto/clipboard"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
integrationTypes "github.com/jesseduffield/lazygit/pkg/integration/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TestDriver struct {
|
||||||
|
gui integrationTypes.GuiDriver
|
||||||
|
keys config.KeybindingConfig
|
||||||
|
inputDelay int
|
||||||
|
*assertionHelper
|
||||||
|
shell *Shell
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewTestDriver(gui integrationTypes.GuiDriver, shell *Shell, keys config.KeybindingConfig, inputDelay int) *TestDriver {
|
||||||
|
return &TestDriver{
|
||||||
|
gui: gui,
|
||||||
|
keys: keys,
|
||||||
|
inputDelay: inputDelay,
|
||||||
|
assertionHelper: &assertionHelper{gui: gui},
|
||||||
|
shell: shell,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// key is something like 'w' or '<space>'. It's best not to pass a direct value,
|
||||||
|
// but instead to go through the default user config to get a more meaningful key name
|
||||||
|
func (self *TestDriver) press(keyStr string) {
|
||||||
|
self.SetCaption(fmt.Sprintf("Pressing %s", keyStr))
|
||||||
|
self.gui.PressKey(keyStr)
|
||||||
|
self.Wait(self.inputDelay)
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`package updates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-errors/errors"
|
||||||
|
|
||||||
|
"github.com/kardianos/osext"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/commands/oscommands"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/common"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/constants"
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Updater checks for updates and does updates
|
||||||
|
type Updater struct {
|
||||||
|
*common.Common
|
||||||
|
Config config.AppConfigurer
|
||||||
|
OSCommand *oscommands.OSCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updaterer implements the check and update methods
|
||||||
|
type Updaterer interface {
|
||||||
|
CheckForNewUpdate()
|
||||||
|
Update()
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IsValidEmail checks if an email address is valid
|
||||||
|
func IsValidEmail(email string) bool {
|
||||||
|
// Using a regex pattern to validate email addresses
|
||||||
|
// This is a simple example and might not cover all edge cases
|
||||||
|
emailPattern := ` + "`" + `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$` + "`" + `
|
||||||
|
match, _ := regexp.MatchString(emailPattern, email)
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
fmt.Fprintf(w, "Hello, the current time is: %s", time.Now().Format(time.RFC3339))
|
||||||
|
})
|
||||||
|
|
||||||
|
port := 8080
|
||||||
|
utils.PrintMessage(fmt.Sprintf("Server is listening on port %d", port))
|
||||||
|
http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// LogMessage represents a log message with its timestamp
|
||||||
|
type LogMessage struct {
|
||||||
|
Timestamp time.Time
|
||||||
|
Message string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log writes a message to the log file along with a timestamp
|
||||||
|
func Log(message string) {
|
||||||
|
logFile, err := os.OpenFile("app.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error opening log file:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer logFile.Close()
|
||||||
|
|
||||||
|
logEntry := LogMessage{
|
||||||
|
Timestamp: time.Now(),
|
||||||
|
Message: message,
|
||||||
|
}
|
||||||
|
|
||||||
|
logLine := fmt.Sprintf("[%s] %s\n", logEntry.Timestamp.Format("2006-01-02 15:04:05"), logEntry.Message)
|
||||||
|
_, err = logFile.WriteString(logLine)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error writing to log file:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
`
|
||||||
|
package encryption
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/aes"
|
||||||
|
"crypto/cipher"
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Encrypt encrypts a plaintext using AES-GCM encryption
|
||||||
|
func Encrypt(key []byte, plaintext []byte) ([]byte, error) {
|
||||||
|
block, err := aes.NewCipher(key)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
aesGCM, err := cipher.NewGCM(block)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
nonce := make([]byte, aesGCM.NonceSize())
|
||||||
|
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ciphertext := aesGCM.Seal(nil, nonce, plaintext, nil)
|
||||||
|
return append(nonce, ciphertext...), nil
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
|
||||||
|
var RandomBranchNames = []string{
|
||||||
|
"hotfix/fix-bug",
|
||||||
|
"r-u-fkn-srs",
|
||||||
|
"iserlohn-build",
|
||||||
|
"hotfix/fezzan-corridor",
|
||||||
|
"terra-investigation",
|
||||||
|
"quash-rebellion",
|
||||||
|
"feature/attack-on-odin",
|
||||||
|
"feature/peace-time",
|
||||||
|
"feature/repair-brunhild",
|
||||||
|
"feature/iserlohn-backdoor",
|
||||||
|
"bugfix/resolve-crash",
|
||||||
|
"enhancement/improve-performance",
|
||||||
|
"experimental/new-feature",
|
||||||
|
"release/v1.0.0",
|
||||||
|
"release/v2.0.0",
|
||||||
|
"chore/update-dependencies",
|
||||||
|
"docs/add-readme",
|
||||||
|
"refactor/cleanup-code",
|
||||||
|
"style/update-css",
|
||||||
|
"test/add-unit-tests",
|
||||||
|
}
|
||||||
|
@ -3,10 +3,14 @@ package components
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
// this is for running shell commands, mostly for the sake of setting up the repo
|
// this is for running shell commands, mostly for the sake of setting up the repo
|
||||||
@ -18,6 +22,8 @@ type Shell struct {
|
|||||||
// when running the shell outside the gui we can directly panic on failure,
|
// when running the shell outside the gui we can directly panic on failure,
|
||||||
// but inside the gui we need to close the gui before panicking
|
// but inside the gui we need to close the gui before panicking
|
||||||
fail func(string)
|
fail func(string)
|
||||||
|
|
||||||
|
randomFileContentIndex int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewShell(dir string, fail func(string)) *Shell {
|
func NewShell(dir string, fail func(string)) *Shell {
|
||||||
@ -122,6 +128,10 @@ func (self *Shell) NewBranch(name string) *Shell {
|
|||||||
return self.RunCommand([]string{"git", "checkout", "-b", name})
|
return self.RunCommand([]string{"git", "checkout", "-b", name})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Shell) NewBranchFrom(name string, from string) *Shell {
|
||||||
|
return self.RunCommand([]string{"git", "checkout", "-b", name, from})
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Shell) Checkout(name string) *Shell {
|
func (self *Shell) Checkout(name string) *Shell {
|
||||||
return self.RunCommand([]string{"git", "checkout", name})
|
return self.RunCommand([]string{"git", "checkout", name})
|
||||||
}
|
}
|
||||||
@ -150,6 +160,10 @@ func (self *Shell) EmptyCommit(message string) *Shell {
|
|||||||
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", message})
|
return self.RunCommand([]string{"git", "commit", "--allow-empty", "-m", message})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Shell) EmptyCommitDaysAgo(message string, daysAgo int) *Shell {
|
||||||
|
return self.RunCommand([]string{"git", "commit", "--allow-empty", "--date", fmt.Sprintf("%d days ago", daysAgo), "-m", message})
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Shell) Revert(ref string) *Shell {
|
func (self *Shell) Revert(ref string) *Shell {
|
||||||
return self.RunCommand([]string{"git", "revert", ref})
|
return self.RunCommand([]string{"git", "revert", ref})
|
||||||
}
|
}
|
||||||
@ -221,6 +235,83 @@ func (self *Shell) CreateNCommitsWithRandomMessages(n int) *Shell {
|
|||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This creates a repo history of commits
|
||||||
|
// It uses a branching strategy where each feature branch is directly branched off
|
||||||
|
// of the master branch
|
||||||
|
// Only to be used in demos
|
||||||
|
func (self *Shell) CreateRepoHistory() *Shell {
|
||||||
|
authors := []string{"Yang Wen-li", "Siegfried Kircheis", "Paul Oberstein", "Oscar Reuenthal", "Fredrica Greenhill"}
|
||||||
|
|
||||||
|
numAuthors := 5
|
||||||
|
numBranches := 10
|
||||||
|
numInitialCommits := 20
|
||||||
|
maxCommitsPerBranch := 5
|
||||||
|
// Each commit will happen on a separate day
|
||||||
|
repoStartDaysAgo := 100
|
||||||
|
|
||||||
|
totalCommits := 0
|
||||||
|
|
||||||
|
// Generate commits
|
||||||
|
for i := 0; i < numInitialCommits; i++ {
|
||||||
|
author := authors[i%numAuthors]
|
||||||
|
commitMessage := RandomCommitMessages[totalCommits%len(RandomCommitMessages)]
|
||||||
|
|
||||||
|
self.SetAuthor(author, "")
|
||||||
|
self.EmptyCommitDaysAgo(commitMessage, repoStartDaysAgo-totalCommits)
|
||||||
|
totalCommits++
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate branches and merges
|
||||||
|
for i := 0; i < numBranches; i++ {
|
||||||
|
// We'll have one author creating all the commits in the branch
|
||||||
|
author := authors[i%numAuthors]
|
||||||
|
branchName := RandomBranchNames[i%len(RandomBranchNames)]
|
||||||
|
|
||||||
|
// Choose a random commit within the last 20 commits on the master branch
|
||||||
|
lastMasterCommit := totalCommits - 1
|
||||||
|
commitOffset := rand.Intn(utils.Min(lastMasterCommit, 5)) + 1
|
||||||
|
|
||||||
|
// Create the feature branch and checkout the chosen commit
|
||||||
|
self.NewBranchFrom(branchName, fmt.Sprintf("master~%d", commitOffset))
|
||||||
|
|
||||||
|
numCommitsInBranch := rand.Intn(maxCommitsPerBranch) + 1
|
||||||
|
for j := 0; j < numCommitsInBranch; j++ {
|
||||||
|
commitMessage := RandomCommitMessages[totalCommits%len(RandomCommitMessages)]
|
||||||
|
|
||||||
|
self.SetAuthor(author, "")
|
||||||
|
self.EmptyCommitDaysAgo(commitMessage, repoStartDaysAgo-totalCommits)
|
||||||
|
totalCommits++
|
||||||
|
}
|
||||||
|
|
||||||
|
self.Checkout("master")
|
||||||
|
|
||||||
|
prevCommitterDate := os.Getenv("GIT_COMMITTER_DATE")
|
||||||
|
prevAuthorDate := os.Getenv("GIT_AUTHOR_DATE")
|
||||||
|
|
||||||
|
commitDate := time.Now().Add(time.Duration(totalCommits-repoStartDaysAgo) * time.Hour * 24)
|
||||||
|
os.Setenv("GIT_COMMITTER_DATE", commitDate.Format(time.RFC3339))
|
||||||
|
os.Setenv("GIT_AUTHOR_DATE", commitDate.Format(time.RFC3339))
|
||||||
|
|
||||||
|
// Merge branch into master
|
||||||
|
self.RunCommand([]string{"git", "merge", "--no-ff", branchName, "-m", fmt.Sprintf("Merge %s into master", branchName)})
|
||||||
|
|
||||||
|
os.Setenv("GIT_COMMITTER_DATE", prevCommitterDate)
|
||||||
|
os.Setenv("GIT_AUTHOR_DATE", prevAuthorDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a commit with a random file
|
||||||
|
// Only to be used in demos
|
||||||
|
func (self *Shell) RandomChangeCommit(message string) *Shell {
|
||||||
|
index := self.randomFileContentIndex
|
||||||
|
self.randomFileContentIndex++
|
||||||
|
randomFileName := fmt.Sprintf("random-%d.go", index)
|
||||||
|
self.CreateFileAndAdd(randomFileName, RandomFileContents[index%len(RandomFileContents)])
|
||||||
|
return self.Commit(message)
|
||||||
|
}
|
||||||
|
|
||||||
func (self *Shell) SetConfig(key string, value string) *Shell {
|
func (self *Shell) SetConfig(key string, value string) *Shell {
|
||||||
self.RunCommand([]string{"git", "config", "--local", key, value})
|
self.RunCommand([]string{"git", "config", "--local", key, value})
|
||||||
return self
|
return self
|
||||||
@ -361,3 +452,10 @@ func (self *Shell) Chdir(path string) *Shell {
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *Shell) SetAuthor(authorName string, authorEmail string) *Shell {
|
||||||
|
self.RunCommand([]string{"git", "config", "--local", "user.name", authorName})
|
||||||
|
self.RunCommand([]string{"git", "config", "--local", "user.email", authorEmail})
|
||||||
|
|
||||||
|
return self
|
||||||
|
}
|
||||||
|
@ -40,12 +40,12 @@ var RebaseFromMarkedBase = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
NavigateToLine(Contains("active one")).
|
NavigateToLine(Contains("active one")).
|
||||||
Press(keys.Commits.MarkCommitAsBaseForRebase).
|
Press(keys.Commits.MarkCommitAsBaseForRebase).
|
||||||
Lines(
|
Lines(
|
||||||
Contains("active three"),
|
Contains("active three").Contains("✓"),
|
||||||
Contains("active two"),
|
Contains("active two").Contains("✓"),
|
||||||
Contains("↑↑↑ Will rebase from here ↑↑↑ active one"),
|
Contains("↑↑↑ Will rebase from here ↑↑↑ active one"),
|
||||||
Contains("three"),
|
Contains("three").DoesNotContain("✓"),
|
||||||
Contains("two"),
|
Contains("two").DoesNotContain("✓"),
|
||||||
Contains("one"),
|
Contains("one").DoesNotContain("✓"),
|
||||||
)
|
)
|
||||||
|
|
||||||
t.Views().Information().Content(Contains("Marked a base commit for rebase"))
|
t.Views().Information().Content(Contains("Marked a base commit for rebase"))
|
||||||
@ -66,13 +66,13 @@ var RebaseFromMarkedBase = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
Confirm()
|
Confirm()
|
||||||
|
|
||||||
t.Views().Commits().Lines(
|
t.Views().Commits().Lines(
|
||||||
Contains("active three"),
|
Contains("active three").DoesNotContain("✓"),
|
||||||
Contains("active two"),
|
Contains("active two").DoesNotContain("✓"),
|
||||||
Contains("target two"),
|
Contains("target two").DoesNotContain("✓"),
|
||||||
Contains("target one"),
|
Contains("target one").DoesNotContain("✓"),
|
||||||
Contains("three"),
|
Contains("three").DoesNotContain("✓"),
|
||||||
Contains("two"),
|
Contains("two").DoesNotContain("✓"),
|
||||||
Contains("one"),
|
Contains("one").DoesNotContain("✓"),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
79
pkg/integration/tests/demo/commit_graph.go
Normal file
79
pkg/integration/tests/demo/commit_graph.go
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
package demo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CommitGraph = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Show commit graph",
|
||||||
|
ExtraCmdArgs: []string{"log"},
|
||||||
|
Skip: false,
|
||||||
|
IsDemo: true,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {
|
||||||
|
config.UserConfig.Gui.NerdFontsVersion = "3"
|
||||||
|
config.UserConfig.Gui.AuthorColors = map[string]string{
|
||||||
|
"Fredrica Greenhill": "#fb5aa3",
|
||||||
|
"Oscar Reuenthal": "#86c82f",
|
||||||
|
"Paul Oberstein": "#ffd500",
|
||||||
|
"Siegfried Kircheis": "#fe7e11",
|
||||||
|
"Yang Wen-li": "#8e3ccb",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.CreateRepoHistory()
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.SetCaptionPrefix("View commit log")
|
||||||
|
t.Wait(1000)
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
IsFocused().
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100).
|
||||||
|
SelectNextItem().
|
||||||
|
Wait(100)
|
||||||
|
},
|
||||||
|
})
|
81
pkg/integration/tests/demo/rebase_onto.go
Normal file
81
pkg/integration/tests/demo/rebase_onto.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package demo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jesseduffield/lazygit/pkg/config"
|
||||||
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RebaseOnto = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
|
Description: "Rebase with '--onto' flag. We start with a feature branch on the develop branch that we want to rebase onto the master branch",
|
||||||
|
ExtraCmdArgs: []string{},
|
||||||
|
Skip: false,
|
||||||
|
IsDemo: true,
|
||||||
|
SetupConfig: func(config *config.AppConfig) {
|
||||||
|
config.UserConfig.Gui.NerdFontsVersion = "3"
|
||||||
|
},
|
||||||
|
SetupRepo: func(shell *Shell) {
|
||||||
|
shell.CreateNCommitsWithRandomMessages(60)
|
||||||
|
shell.NewBranch("develop")
|
||||||
|
|
||||||
|
shell.SetAuthor("Joe Blow", "joeblow@gmail.com")
|
||||||
|
|
||||||
|
shell.RandomChangeCommit("Develop commit 1")
|
||||||
|
shell.RandomChangeCommit("Develop commit 2")
|
||||||
|
shell.RandomChangeCommit("Develop commit 3")
|
||||||
|
|
||||||
|
shell.SetAuthor("Jesse Duffield", "jesseduffield@gmail.com")
|
||||||
|
|
||||||
|
shell.NewBranch("feature/demo")
|
||||||
|
|
||||||
|
shell.RandomChangeCommit("Feature commit 1")
|
||||||
|
shell.RandomChangeCommit("Feature commit 2")
|
||||||
|
shell.RandomChangeCommit("Feature commit 3")
|
||||||
|
|
||||||
|
shell.CloneIntoRemote("origin")
|
||||||
|
|
||||||
|
shell.SetBranchUpstream("feature/demo", "origin/feature/demo")
|
||||||
|
shell.SetBranchUpstream("develop", "origin/develop")
|
||||||
|
},
|
||||||
|
Run: func(t *TestDriver, keys config.KeybindingConfig) {
|
||||||
|
t.SetCaptionPrefix("Rebase from marked base commit")
|
||||||
|
t.Wait(1000)
|
||||||
|
|
||||||
|
// first we focus the commits view, then expand to show the branches against each commit
|
||||||
|
// Then we go back to normal value, mark the last develop branch commit as the marked commit
|
||||||
|
// Then go to the branches view and press 'r' on the master branch to rebase onto it
|
||||||
|
// then we force push our changes.
|
||||||
|
|
||||||
|
t.Views().Commits().
|
||||||
|
Focus().
|
||||||
|
Press(keys.Universal.PrevScreenMode).
|
||||||
|
Wait(500).
|
||||||
|
NavigateToLine(Contains("Develop commit 3")).
|
||||||
|
Wait(500).
|
||||||
|
Press(keys.Commits.MarkCommitAsBaseForRebase).
|
||||||
|
Wait(1000).
|
||||||
|
Press(keys.Universal.NextScreenMode).
|
||||||
|
Wait(500)
|
||||||
|
|
||||||
|
t.Views().Branches().
|
||||||
|
Focus().
|
||||||
|
Wait(500).
|
||||||
|
NavigateToLine(Contains("master")).
|
||||||
|
Wait(500).
|
||||||
|
Press(keys.Branches.RebaseBranch).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Menu().
|
||||||
|
Title(Contains("Rebase 'feature/demo' from marked base onto 'master'")).
|
||||||
|
Select(Contains("Simple rebase")).
|
||||||
|
Confirm()
|
||||||
|
}).
|
||||||
|
Wait(1000).
|
||||||
|
Press(keys.Universal.Push).
|
||||||
|
Tap(func() {
|
||||||
|
t.ExpectPopup().Confirmation().
|
||||||
|
Title(Contains("Force push")).
|
||||||
|
Content(AnyString()).
|
||||||
|
Wait(500).
|
||||||
|
Confirm()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
@ -5,8 +5,6 @@ import (
|
|||||||
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
. "github.com/jesseduffield/lazygit/pkg/integration/components"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO: fix confirmation view wrapping issue: https://github.com/jesseduffield/lazygit/issues/2872
|
|
||||||
|
|
||||||
var Undo = NewIntegrationTest(NewIntegrationTestArgs{
|
var Undo = NewIntegrationTest(NewIntegrationTestArgs{
|
||||||
Description: "Undo",
|
Description: "Undo",
|
||||||
ExtraCmdArgs: []string{},
|
ExtraCmdArgs: []string{},
|
||||||
@ -38,14 +36,6 @@ var Undo = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
Confirm()
|
Confirm()
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmRedo := func() {
|
|
||||||
t.ExpectPopup().Confirmation().
|
|
||||||
Title(Equals("Redo")).
|
|
||||||
Content(MatchesRegexp(`Are you sure you want to hard reset to '.*'\? An auto-stash will be performed if necessary\.`)).
|
|
||||||
Wait(500).
|
|
||||||
Confirm()
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Views().Commits().Focus().
|
t.Views().Commits().Focus().
|
||||||
SetCaptionPrefix("Drop two commits").
|
SetCaptionPrefix("Drop two commits").
|
||||||
Wait(1000).
|
Wait(1000).
|
||||||
@ -58,12 +48,6 @@ var Undo = NewIntegrationTest(NewIntegrationTestArgs{
|
|||||||
Press(keys.Universal.Undo).
|
Press(keys.Universal.Undo).
|
||||||
Tap(confirmUndo).
|
Tap(confirmUndo).
|
||||||
Press(keys.Universal.Undo).
|
Press(keys.Universal.Undo).
|
||||||
Tap(confirmUndo).
|
Tap(confirmUndo)
|
||||||
SetCaptionPrefix("Redo the drops").
|
|
||||||
Wait(1000).
|
|
||||||
Press(keys.Universal.Redo).
|
|
||||||
Tap(confirmRedo).
|
|
||||||
Press(keys.Universal.Redo).
|
|
||||||
Tap(confirmRedo)
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -93,11 +93,13 @@ var tests = []*components.IntegrationTest{
|
|||||||
demo.Bisect,
|
demo.Bisect,
|
||||||
demo.CherryPick,
|
demo.CherryPick,
|
||||||
demo.CommitAndPush,
|
demo.CommitAndPush,
|
||||||
|
demo.CommitGraph,
|
||||||
demo.CustomCommand,
|
demo.CustomCommand,
|
||||||
demo.CustomPatch,
|
demo.CustomPatch,
|
||||||
demo.Filter,
|
demo.Filter,
|
||||||
demo.InteractiveRebase,
|
demo.InteractiveRebase,
|
||||||
demo.NukeWorkingTree,
|
demo.NukeWorkingTree,
|
||||||
|
demo.RebaseOnto,
|
||||||
demo.StageLines,
|
demo.StageLines,
|
||||||
demo.Undo,
|
demo.Undo,
|
||||||
demo.WorktreeCreateFromBranches,
|
demo.WorktreeCreateFromBranches,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user