Skip to content

Commit

Permalink
Add manual code edit functionality
Browse files Browse the repository at this point in the history
- Bunch of new tests have been added/fixed!
- testhelper package has been added
  • Loading branch information
mkchoi212 committed May 21, 2018
1 parent 84fa845 commit afe8327
Show file tree
Hide file tree
Showing 24 changed files with 506 additions and 386 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ w - show more lines up
s - show more lines down
a - use local version
d - use incoming version
e - manually edit code
j - scroll down
k - scroll up
Expand Down
4 changes: 2 additions & 2 deletions assets/doc/fac.1
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.\" Automatically generated by Pandoc 2.0.2
.\" Automatically generated by Pandoc 2.2.1
.\"
.TH "fac" "1"
.hy
Expand Down Expand Up @@ -39,7 +39,7 @@ The commands have been preset to the following specifications:
.PD 0
.P
.PD
\f[B]d\f[] \- use incoming version
\f[B]d\f[] \- use incoming version \f[B]e\f[] \- manually edit code
.PP
\f[B]j\f[] \- scroll down
.PD 0
Expand Down
1 change: 1 addition & 0 deletions assets/doc/fac.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ The commands have been preset to the following specifications:
**s** - show more lines down
**a** - use local version
**d** - use incoming version
**e** - manually edit code

**j** - scroll down
**k** - scroll up
Expand Down
16 changes: 11 additions & 5 deletions conflict/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,24 @@ func run(name string, dir string, args ...string) (stdout string, stderr string,
return
}

// MarkerLocations returns line numbers of all git conflict markers
func MarkerLocations(cwd string) ([]string, error) {
stdout, stderr, _ := run("git", cwd, "--no-pager", "diff", "--check")
// conflictedFiles returns a list of conflicted files
func conflictedFiles(cwd string) ([]string, error) {
stdout, stderr, _ := run("git", cwd, "--no-pager", "diff", "--name-only", "--diff-filter=U")

if len(stderr) != 0 {
return nil, errors.New(stderr)
}

stdout = strings.TrimSuffix(stdout, "\n")
if stdout == "" {
return []string{}, nil
}

return strings.Split(stdout, "\n"), nil
}

// TopLevelPath finds the top level path of the current git repository
func TopLevelPath(cwd string) (string, error) {
// topLevelPath finds the top level path of the current git repository
func topLevelPath(cwd string) (string, error) {
stdout, stderr, _ := run("git", cwd, "rev-parse", "--show-toplevel")

if len(stderr) != 0 {
Expand Down
43 changes: 20 additions & 23 deletions conflict/command_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import (
"os"
"os/exec"
"strconv"
"strings"
"testing"

"github.com/mkchoi212/fac/testhelper"
)

var mockValidDirectory = "/"
Expand Down Expand Up @@ -40,12 +41,8 @@ func TestHelperProcess(t *testing.T) {
os.Exit(0)
}

// MarkerLocation arguements
if args == "--no-pager,diff,--check" {
allCheckOutput := append([]string{}, loremDiffCheck...)
allCheckOutput = append(allCheckOutput, ccDiffCheck...)
allCheckOutput = append(allCheckOutput, readmeDiffCheck...)
fmt.Fprintf(os.Stdout, strings.Join(allCheckOutput, "\n"))
if args == "--no-pager,diff,--name-only,--diff-filter=U" {
fmt.Fprintf(os.Stdout, "lorem_ipsum\nassets/README.md\n")
os.Exit(0)
}

Expand All @@ -70,42 +67,42 @@ func TestRun(t *testing.T) {
for _, test := range commands {
stdout, stderr, exitCode := run(test.command, ".", strconv.FormatBool(test.ok))

if test.ok && exitCode != 0 {
t.Errorf("run failed: got %s with exit code %d, expected no errors", stderr, exitCode)
} else if !(test.ok) && exitCode == 0 {
t.Errorf("run failed: got %s with exit code %d, expected errors", stdout, exitCode)
if test.ok {
testhelper.Assert(t, exitCode == 0, "expected no errors but got %s", stderr)
} else {
testhelper.Assert(t, exitCode != 0, "expected errors but got %s", stdout)
}
}
}

func TestTopLevelPath(t *testing.T) {
func TestConflictedFiles(t *testing.T) {
execCommand = mockExecCommand
defer func() { execCommand = exec.Command }()

tests := []string{mockValidDirectory, mockInvalidDirectory}
for _, test := range tests {
out, err := TopLevelPath(test)
out, err := conflictedFiles(test)

if test == mockValidDirectory && err != nil {
t.Errorf("TopLevelPath failed: got %s, expected no errors", err.Error())
} else if test == mockInvalidDirectory && err == nil {
t.Errorf("TopLevelPath failed: got %s, expected errors", out)
if test == mockValidDirectory {
testhelper.Ok(t, err)
} else if test == mockInvalidDirectory {
testhelper.Assert(t, err != nil, "expected errors but got %s", out)
}
}
}

func TestMarkerLocations(t *testing.T) {
func TestTopLevelPath(t *testing.T) {
execCommand = mockExecCommand
defer func() { execCommand = exec.Command }()

tests := []string{mockValidDirectory, mockInvalidDirectory}
for _, test := range tests {
out, err := MarkerLocations(test)
out, err := topLevelPath(test)

if test == mockValidDirectory && err != nil {
t.Errorf("TopLevelPath failed: got %s, expected no errors", err.Error())
} else if test == mockInvalidDirectory && err == nil {
t.Errorf("TopLevelPath failed: got %s, expected errors", out)
if test == mockValidDirectory {
testhelper.Ok(t, err)
} else if test == mockInvalidDirectory {
testhelper.Assert(t, err != nil, "expected errors but got %s", out)
}
}
}
56 changes: 28 additions & 28 deletions conflict/conflict.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package conflict

import (
"bytes"
"errors"
"sort"
"strings"

Expand Down Expand Up @@ -35,42 +36,17 @@ type Conflict struct {
BottomPeek int
}

// Supported git conflict styles
const (
text = iota
start
diff3
separator
end
)

const (
Local = 1
Incoming = 2
)

// IdentifyStyle identifies the conflict marker style of provided text
func IdentifyStyle(line string) (style int) {
line = strings.TrimSpace(line)

if strings.Contains(line, "<<<<<<<") {
style = start
} else if strings.Contains(line, ">>>>>>>") {
style = end
} else if line == "||||||| merged common ancestors" {
style = diff3
} else if line == "=======" {
style = separator
} else {
style = text
}
return
}
var ErrInvalidManualInput = errors.New("Newly edited code is invalid")

// Valid checks if the parsed conflict has corresponding begin, separator,
// and middle line numbers
func (c *Conflict) Valid() bool {
return c.File != nil && c.Middle != 0 && c.End != 0
return c.Start != -1 && c.Middle != 0 && c.End != 0
}

// Equal checks if two `Conflict`s are equal
Expand All @@ -95,6 +71,30 @@ func (c *Conflict) Extract(lines []string) error {
return nil
}

// Update takes the user's input from an editor and updates the current
// representation of `Conflict`
func (c *Conflict) Update(incoming []string) (err error) {
conflicts, err := GroupConflictMarkers(incoming)
if err != nil || len(conflicts) != 1 {
return ErrInvalidManualInput
}

updated := conflicts[0]
if err = updated.Extract(incoming); err != nil {
return
}

updated.File = c.File
if err = updated.HighlightSyntax(); err != nil {
return
}

c.IncomingLines, c.ColoredIncomingLines = updated.IncomingLines, updated.ColoredIncomingLines
c.LocalLines, c.ColoredLocalLines = updated.LocalLines, updated.ColoredLocalLines
c.LocalPureLines = updated.LocalPureLines
return
}

// PaddingLines returns top and bottom padding lines based on
// `TopPeek` and `BottomPeek` values
func (c *Conflict) PaddingLines() (topPadding, bottomPadding []string) {
Expand Down Expand Up @@ -156,7 +156,7 @@ func (c *Conflict) HighlightSyntax() error {
tokenizer:
for i, block := range [][]string{c.LocalLines, c.IncomingLines} {
for _, line := range block {
if IdentifyStyle(line) == diff3 {
if identifyStyle(line) == diff3 {
colorLine = color.Red(color.Regular, line)
} else {
if it, err = lexer.Tokenise(nil, line); err != nil {
Expand Down
Loading

0 comments on commit afe8327

Please sign in to comment.