mirror of
				https://github.com/jesseduffield/lazygit.git
				synced 2025-10-30 23:57:43 +02:00 
			
		
		
		
	better handling of merge conflicts
This commit is contained in:
		| @@ -29,12 +29,24 @@ func stagedFiles(files []GitFile) []GitFile { | ||||
| 	return result | ||||
| } | ||||
|  | ||||
| func stageSelectedFile(g *gocui.Gui) error { | ||||
| 	file, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return stageFile(file.Name) | ||||
| } | ||||
|  | ||||
| func handleFilePress(g *gocui.Gui, v *gocui.View) error { | ||||
| 	file, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if file.HasMergeConflicts { | ||||
| 		return handleSwitchToMerge(g, v) | ||||
| 	} | ||||
|  | ||||
| 	if file.HasUnstagedChanges { | ||||
| 		stageFile(file.Name) | ||||
| 	} else { | ||||
| @@ -64,22 +76,22 @@ func getSelectedFile(g *gocui.Gui) (GitFile, error) { | ||||
| } | ||||
|  | ||||
| func handleFileRemove(g *gocui.Gui, v *gocui.View) error { | ||||
|   file, err := getSelectedFile(g) | ||||
|   if err != nil { | ||||
|     return err | ||||
|   } | ||||
|   var deleteVerb string | ||||
|   if file.Tracked { | ||||
|     deleteVerb = "checkout" | ||||
|   } else { | ||||
|     deleteVerb = "delete" | ||||
|   } | ||||
|   return createConfirmationPanel(g, v, strings.Title(deleteVerb)+" file", "Are you sure you want to "+deleteVerb+" "+file.Name+" (you will lose your changes)?", func(g *gocui.Gui, v *gocui.View) error { | ||||
|     if err := removeFile(file); err != nil { | ||||
|       panic(err) | ||||
|     } | ||||
|     return refreshFiles(g) | ||||
|   }, nil) | ||||
| 	file, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	var deleteVerb string | ||||
| 	if file.Tracked { | ||||
| 		deleteVerb = "checkout" | ||||
| 	} else { | ||||
| 		deleteVerb = "delete" | ||||
| 	} | ||||
| 	return createConfirmationPanel(g, v, strings.Title(deleteVerb)+" file", "Are you sure you want to "+deleteVerb+" "+file.Name+" (you will lose your changes)?", func(g *gocui.Gui, v *gocui.View) error { | ||||
| 		if err := removeFile(file); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		return refreshFiles(g) | ||||
| 	}, nil) | ||||
| } | ||||
|  | ||||
| func handleIgnoreFile(g *gocui.Gui, v *gocui.View) error { | ||||
| @@ -176,7 +188,7 @@ func handleVsCodeFileOpen(g *gocui.Gui, v *gocui.View) error { | ||||
| } | ||||
|  | ||||
| func handleRefreshFiles(g *gocui.Gui, v *gocui.View) error { | ||||
|   return refreshFiles(g) | ||||
| 	return refreshFiles(g) | ||||
| } | ||||
|  | ||||
| func refreshStateGitFiles() { | ||||
| @@ -291,7 +303,7 @@ func handleSwitchToMerge(g *gocui.Gui, v *gocui.View) error { | ||||
| 		return nil | ||||
| 	} | ||||
| 	if !file.HasMergeConflicts { | ||||
| 		return nil | ||||
| 		return createErrorPanel(g, "This file has no merge conflicts") | ||||
| 	} | ||||
| 	switchFocus(g, v, mergeView) | ||||
| 	return refreshMergePanel(g) | ||||
|   | ||||
							
								
								
									
										239
									
								
								gui.go
									
									
									
									
									
								
							
							
						
						
									
										239
									
								
								gui.go
									
									
									
									
									
								
							| @@ -66,124 +66,127 @@ func handleRefresh(g *gocui.Gui, v *gocui.View) error { | ||||
| } | ||||
|  | ||||
| func keybindings(g *gocui.Gui) error { | ||||
|   if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, nextView); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", 'q', gocui.ModNone, quit); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", gocui.KeyPgup, gocui.ModNone, scrollUpMain); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", gocui.KeyPgdn, gocui.ModNone, scrollDownMain); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", 'P', gocui.ModNone, pushFiles); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", 'p', gocui.ModNone, pullFiles); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("", 'R', gocui.ModNone, handleRefresh); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'c', gocui.ModNone, handleCommitPress); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", gocui.KeySpace, gocui.ModNone, handleFilePress); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'd', gocui.ModNone, handleFileRemove); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'm', gocui.ModNone, handleSwitchToMerge); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'o', gocui.ModNone, handleFileOpen); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 's', gocui.ModNone, handleSublimeFileOpen); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'i', gocui.ModNone, handleIgnoreFile); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'r', gocui.ModNone, handleRefreshFiles); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'S', gocui.ModNone, handleStashSave); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("files", 'a', gocui.ModNone, handleAbortMerge); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeyArrowUp, gocui.ModNone, handleSelectTop); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeyEsc, gocui.ModNone, handleEscapeMerge); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeyArrowDown, gocui.ModNone, handleSelectBottom); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeySpace, gocui.ModNone, handlePickConflict); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeyArrowLeft, gocui.ModNone, handleSelectPrevConflict); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", gocui.KeyArrowRight, gocui.ModNone, handleSelectNextConflict); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("main", 'z', gocui.ModNone, handlePopFileSnapshot); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("branches", gocui.KeySpace, gocui.ModNone, handleBranchPress); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("branches", 'c', gocui.ModNone, handleCheckoutByName); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("branches", 'F', gocui.ModNone, handleForceCheckout); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("branches", 'n', gocui.ModNone, handleNewBranch); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("branches", 'm', gocui.ModNone, handleMerge); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("commits", 's', gocui.ModNone, handleCommitSquashDown); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("commits", 'r', gocui.ModNone, handleRenameCommit); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("commits", 'g', gocui.ModNone, handleResetToCommit); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("stash", gocui.KeySpace, gocui.ModNone, handleStashApply); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   // TODO: come up with a better keybinding (p/P used for pushing/pulling which | ||||
|   // I'd like to be global. Perhaps all global keybindings should use a modifier | ||||
|   // like command? But then there's gonna be hotkey conflicts with the terminal | ||||
|   if err := g.SetKeybinding("stash", 'k', gocui.ModNone, handleStashPop); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := g.SetKeybinding("stash", 'd', gocui.ModNone, handleStashDrop); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   return nil | ||||
| 	if err := g.SetKeybinding("", gocui.KeyTab, gocui.ModNone, nextView); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", 'q', gocui.ModNone, quit); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", gocui.KeyCtrlC, gocui.ModNone, quit); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", gocui.KeyArrowDown, gocui.ModNone, cursorDown); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", gocui.KeyArrowUp, gocui.ModNone, cursorUp); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", gocui.KeyPgup, gocui.ModNone, scrollUpMain); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", gocui.KeyPgdn, gocui.ModNone, scrollDownMain); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", 'P', gocui.ModNone, pushFiles); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", 'p', gocui.ModNone, pullFiles); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("", 'R', gocui.ModNone, handleRefresh); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'c', gocui.ModNone, handleCommitPress); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", gocui.KeySpace, gocui.ModNone, handleFilePress); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'd', gocui.ModNone, handleFileRemove); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'm', gocui.ModNone, handleSwitchToMerge); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'o', gocui.ModNone, handleFileOpen); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 's', gocui.ModNone, handleSublimeFileOpen); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'i', gocui.ModNone, handleIgnoreFile); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'r', gocui.ModNone, handleRefreshFiles); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'S', gocui.ModNone, handleStashSave); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("files", 'a', gocui.ModNone, handleAbortMerge); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeyArrowUp, gocui.ModNone, handleSelectTop); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeyEsc, gocui.ModNone, handleEscapeMerge); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeyArrowDown, gocui.ModNone, handleSelectBottom); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeySpace, gocui.ModNone, handlePickHunk); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", 'b', gocui.ModNone, handlePickBothHunks); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeyArrowLeft, gocui.ModNone, handleSelectPrevConflict); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", gocui.KeyArrowRight, gocui.ModNone, handleSelectNextConflict); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("main", 'z', gocui.ModNone, handlePopFileSnapshot); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("branches", gocui.KeySpace, gocui.ModNone, handleBranchPress); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("branches", 'c', gocui.ModNone, handleCheckoutByName); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("branches", 'F', gocui.ModNone, handleForceCheckout); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("branches", 'n', gocui.ModNone, handleNewBranch); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("branches", 'm', gocui.ModNone, handleMerge); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("commits", 's', gocui.ModNone, handleCommitSquashDown); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("commits", 'r', gocui.ModNone, handleRenameCommit); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("commits", 'g', gocui.ModNone, handleResetToCommit); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("stash", gocui.KeySpace, gocui.ModNone, handleStashApply); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	// TODO: come up with a better keybinding (p/P used for pushing/pulling which | ||||
| 	// I'd like to be global. Perhaps all global keybindings should use a modifier | ||||
| 	// like command? But then there's gonna be hotkey conflicts with the terminal | ||||
| 	if err := g.SetKeybinding("stash", 'k', gocui.ModNone, handleStashPop); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := g.SetKeybinding("stash", 'd', gocui.ModNone, handleStashDrop); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func layout(g *gocui.Gui) error { | ||||
|   | ||||
							
								
								
									
										136
									
								
								merge_panel.go
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								merge_panel.go
									
									
									
									
									
								
							| @@ -6,6 +6,7 @@ import ( | ||||
| 	"bufio" | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"math" | ||||
| 	"os" | ||||
| 	"strings" | ||||
|  | ||||
| @@ -86,16 +87,21 @@ func handleSelectPrevConflict(g *gocui.Gui, v *gocui.View) error { | ||||
| 	return refreshMergePanel(g) | ||||
| } | ||||
|  | ||||
| func isIndexToDelete(i int, conflict conflict, top bool) bool { | ||||
| func isIndexToDelete(i int, conflict conflict, pick string) bool { | ||||
| 	return i == conflict.middle || | ||||
| 		i == conflict.start || | ||||
| 		i == conflict.end || | ||||
| 		(!top && i > conflict.start && i < conflict.middle) || | ||||
| 		(top && i > conflict.middle && i < conflict.end) | ||||
| 		pick != "both" && | ||||
| 			(pick == "bottom" && i > conflict.start && i < conflict.middle) || | ||||
| 		(pick == "top" && i > conflict.middle && i < conflict.end) | ||||
| } | ||||
|  | ||||
| func resolveConflict(filename string, conflict conflict, top bool) error { | ||||
| 	file, err := os.Open(filename) | ||||
| func resolveConflict(g *gocui.Gui, conflict conflict, pick string) error { | ||||
| 	gitFile, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	file, err := os.Open(gitFile.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -108,16 +114,20 @@ func resolveConflict(filename string, conflict conflict, top bool) error { | ||||
| 		if err != nil { | ||||
| 			break | ||||
| 		} | ||||
| 		if !isIndexToDelete(i, conflict, top) { | ||||
| 		if !isIndexToDelete(i, conflict, pick) { | ||||
| 			output += line | ||||
| 		} | ||||
| 	} | ||||
| 	devLog(output) | ||||
| 	return ioutil.WriteFile(filename, []byte(output), 0644) | ||||
| 	return ioutil.WriteFile(gitFile.Name, []byte(output), 0644) | ||||
| } | ||||
|  | ||||
| func pushFileSnapshot(filename string) error { | ||||
| 	content, err := catFile(filename) | ||||
| func pushFileSnapshot(g *gocui.Gui) error { | ||||
| 	gitFile, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	content, err := catFile(gitFile.Name) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -139,14 +149,25 @@ func handlePopFileSnapshot(g *gocui.Gui, v *gocui.View) error { | ||||
| 	return refreshMergePanel(g) | ||||
| } | ||||
|  | ||||
| func handlePickConflict(g *gocui.Gui, v *gocui.View) error { | ||||
| func handlePickHunk(g *gocui.Gui, v *gocui.View) error { | ||||
| 	conflict := state.Conflicts[state.ConflictIndex] | ||||
| 	gitFile, err := getSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	pushFileSnapshot(g) | ||||
| 	pick := "bottom" | ||||
| 	if state.ConflictTop { | ||||
| 		pick = "top" | ||||
| 	} | ||||
| 	pushFileSnapshot(gitFile.Name) | ||||
| 	err = resolveConflict(gitFile.Name, conflict, state.ConflictTop) | ||||
| 	err := resolveConflict(g, conflict, pick) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	refreshMergePanel(g) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func handlePickBothHunks(g *gocui.Gui, v *gocui.View) error { | ||||
| 	conflict := state.Conflicts[state.ConflictIndex] | ||||
| 	pushFileSnapshot(g) | ||||
| 	err := resolveConflict(g, conflict, "both") | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| @@ -159,46 +180,48 @@ func currentViewName(g *gocui.Gui) string { | ||||
| } | ||||
|  | ||||
| func refreshMergePanel(g *gocui.Gui) error { | ||||
|   cat, err := catSelectedFile(g) | ||||
|   if err != nil { | ||||
|     return err | ||||
|   } | ||||
|   state.Conflicts, err = findConflicts(cat) | ||||
|   if err != nil { | ||||
|     return err | ||||
|   } | ||||
| 	cat, err := catSelectedFile(g) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	state.Conflicts, err = findConflicts(cat) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
|   if len(state.Conflicts) == 0 { | ||||
|     state.ConflictIndex = 0 | ||||
|   } else if state.ConflictIndex > len(state.Conflicts)-1 { | ||||
|     state.ConflictIndex = len(state.Conflicts) - 1 | ||||
|   } | ||||
|   hasFocus := currentViewName(g) == "main" | ||||
|   if hasFocus { | ||||
|     renderMergeOptions(g) | ||||
|   } | ||||
|   content, err := coloredConflictFile(cat, state.Conflicts, state.ConflictIndex, state.ConflictTop, hasFocus) | ||||
|   if err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if err := scrollToConflict(g); err != nil { | ||||
|     return err | ||||
|   } | ||||
|   return renderString(g, "main", content) | ||||
| 	if len(state.Conflicts) == 0 { | ||||
| 		return handleCompleteMerge(g) | ||||
| 	} else if state.ConflictIndex > len(state.Conflicts)-1 { | ||||
| 		state.ConflictIndex = len(state.Conflicts) - 1 | ||||
| 	} | ||||
| 	hasFocus := currentViewName(g) == "main" | ||||
| 	if hasFocus { | ||||
| 		renderMergeOptions(g) | ||||
| 	} | ||||
| 	content, err := coloredConflictFile(cat, state.Conflicts, state.ConflictIndex, state.ConflictTop, hasFocus) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := scrollToConflict(g); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return renderString(g, "main", content) | ||||
| } | ||||
|  | ||||
| func scrollToConflict(g *gocui.Gui) error { | ||||
|   mainView, err := g.View("main") | ||||
|   if err != nil { | ||||
|     return err | ||||
|   } | ||||
|   if len(state.Conflicts) == 0 { | ||||
|     return nil | ||||
|   } | ||||
|   conflict := state.Conflicts[state.ConflictIndex] | ||||
|   ox, oy := mainView.Origin() | ||||
|   devLog(oy, conflict.start) | ||||
|   return mainView.SetOrigin(ox, conflict.start) | ||||
| 	mainView, err := g.View("main") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if len(state.Conflicts) == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 	conflict := state.Conflicts[state.ConflictIndex] | ||||
| 	ox, _ := mainView.Origin() | ||||
| 	_, height := mainView.Size() | ||||
| 	conflictMiddle := (conflict.end + conflict.start) / 2 | ||||
| 	newOriginY := int(math.Max(0, float64(conflictMiddle-(height/2)))) | ||||
| 	return mainView.SetOrigin(ox, newOriginY) | ||||
| } | ||||
|  | ||||
| func switchToMerging(g *gocui.Gui) error { | ||||
| @@ -216,6 +239,7 @@ func renderMergeOptions(g *gocui.Gui) error { | ||||
| 		"up/down":    "pick hunk", | ||||
| 		"left/right": "previous/next commit", | ||||
| 		"space":      "pick hunk", | ||||
| 		"b":          "pick both hunks", | ||||
| 		"z":          "undo", | ||||
| 	}) | ||||
| } | ||||
| @@ -228,3 +252,13 @@ func handleEscapeMerge(g *gocui.Gui, v *gocui.View) error { | ||||
| 	refreshFiles(g) | ||||
| 	return switchFocus(g, v, filesView) | ||||
| } | ||||
|  | ||||
| func handleCompleteMerge(g *gocui.Gui) error { | ||||
| 	filesView, err := g.View("files") | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	stageSelectedFile(g) | ||||
| 	refreshFiles(g) | ||||
| 	return switchFocus(g, nil, filesView) | ||||
| } | ||||
|   | ||||
| @@ -18,19 +18,31 @@ cd ${reponame} | ||||
|  | ||||
| git init | ||||
|  | ||||
| function add_spacing { | ||||
|   for i in {1..60} | ||||
|   do | ||||
|     echo "..." >> $1 | ||||
|   done | ||||
| } | ||||
|  | ||||
| echo "Here is a story that has been told throuhg the ages" >> file1 | ||||
|  | ||||
| git add file1 | ||||
| git commit -m "first commit" | ||||
|  | ||||
| git checkout -b develop | ||||
|  | ||||
| echo "once upon a time there was a dog" >> file1 | ||||
| add_spacing file1 | ||||
| echo "once upon a time there was another dog" >> file1 | ||||
| git add file1 | ||||
| git commit -m "first commit on develop" | ||||
|  | ||||
| git checkout master | ||||
|  | ||||
| echo "once upon a time there was a cat" >> file1 | ||||
| add_spacing file1 | ||||
| echo "once upon a time there was another cat" >> file1 | ||||
| git add file1 | ||||
| git commit -m "first commit on develop" | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user