Merge pull request #526 from joshbetz/fix/filename-form

Normalize filenames before comparing.
diff --git a/utils/merkletrie/noder/path.go b/utils/merkletrie/noder/path.go
index 85742db..d2e2932 100644
--- a/utils/merkletrie/noder/path.go
+++ b/utils/merkletrie/noder/path.go
@@ -3,6 +3,8 @@
 import (
 	"bytes"
 	"strings"
+
+	"golang.org/x/text/unicode/norm"
 )
 
 // Path values represent a noder and its ancestors.  The root goes first
@@ -78,7 +80,11 @@
 		case i == len(p):
 			return -1
 		default:
-			cmp := strings.Compare(p[i].Name(), other[i].Name())
+			form := norm.Form(norm.NFC)
+			this := form.String(p[i].Name())
+			that := form.String(other[i].Name())
+
+			cmp := strings.Compare(this, that)
 			if cmp != 0 {
 				return cmp
 			}
diff --git a/utils/merkletrie/noder/path_test.go b/utils/merkletrie/noder/path_test.go
index 44e3c3c..be25444 100644
--- a/utils/merkletrie/noder/path_test.go
+++ b/utils/merkletrie/noder/path_test.go
@@ -1,6 +1,9 @@
 package noder
 
-import . "gopkg.in/check.v1"
+import (
+	"golang.org/x/text/unicode/norm"
+	. "gopkg.in/check.v1"
+)
 
 type PathSuite struct{}
 
@@ -149,3 +152,10 @@
 	c.Assert(p1.Compare(p2), Equals, 1)
 	c.Assert(p2.Compare(p1), Equals, -1)
 }
+
+func (s *PathSuite) TestCompareNormalization(c *C) {
+	p1 := Path([]Noder{&noderMock{name: norm.Form(norm.NFKC).String("페")}})
+	p2 := Path([]Noder{&noderMock{name: norm.Form(norm.NFKD).String("페")}})
+	c.Assert(p1.Compare(p2), Equals, 0)
+	c.Assert(p2.Compare(p1), Equals, 0)
+}
diff --git a/worktree_test.go b/worktree_test.go
index c14d3bc..3ca26bc 100644
--- a/worktree_test.go
+++ b/worktree_test.go
@@ -7,6 +7,8 @@
 	"os"
 	"path/filepath"
 
+	"golang.org/x/text/unicode/norm"
+
 	"gopkg.in/src-d/go-git.v4/config"
 	"gopkg.in/src-d/go-git.v4/plumbing"
 	"gopkg.in/src-d/go-git.v4/plumbing/filemode"
@@ -304,6 +306,47 @@
 	c.Assert(err, IsNil)
 }
 
+func (s *WorktreeSuite) TestFilenameNormalization(c *C) {
+	url := c.MkDir()
+	path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
+
+	server, err := PlainClone(url, false, &CloneOptions{
+		URL: path,
+	})
+
+	filename := "페"
+
+	w, err := server.Worktree()
+	c.Assert(err, IsNil)
+	util.WriteFile(w.Filesystem, filename, []byte("foo"), 0755)
+	_, err = w.Add(filename)
+	c.Assert(err, IsNil)
+	_, err = w.Commit("foo", &CommitOptions{Author: defaultSignature()})
+	c.Assert(err, IsNil)
+
+	r, err := Clone(memory.NewStorage(), memfs.New(), &CloneOptions{
+		URL: url,
+	})
+
+	w, err = r.Worktree()
+	c.Assert(err, IsNil)
+
+	status, err := w.Status()
+	c.Assert(err, IsNil)
+	c.Assert(status.IsClean(), Equals, true)
+
+	err = w.Filesystem.Remove(filename)
+	c.Assert(err, IsNil)
+
+	modFilename := norm.Form(norm.NFKD).String(filename)
+	util.WriteFile(w.Filesystem, modFilename, []byte("foo"), 0755)
+	_, err = w.Add(filename)
+
+	status, err = w.Status()
+	c.Assert(err, IsNil)
+	c.Assert(status.IsClean(), Equals, true)
+}
+
 func (s *WorktreeSuite) TestCheckoutSubmodule(c *C) {
 	url := "https://github.com/git-fixtures/submodule.git"
 	r := s.NewRepositoryWithEmptyWorktree(fixtures.ByURL(url).One())