diff --git a/commands/server.go b/commands/server.go index 708912fbb..57f96a1bd 100644 --- a/commands/server.go +++ b/commands/server.go @@ -150,14 +150,15 @@ func server(cmd *cobra.Command, args []string) { // Watch runs its own server as part of the routine if serverWatch { - watched := getDirList() - workingDir := helpers.AbsPathify(viper.GetString("WorkingDir")) - for i, dir := range watched { - watched[i], _ = helpers.GetRelativePath(dir, workingDir) + watchDirs := getDirList() + baseWatchDir := helpers.AbsPathify(viper.GetString("WorkingDir")) + for i, dir := range watchDirs { + watchDirs[i], _ = helpers.GetRelativePath(dir, baseWatchDir) } - unique := strings.Join(helpers.RemoveSubpaths(watched), ",") - jww.FEEDBACK.Printf("Watching for changes in %s/{%s}\n", workingDir, unique) + rootWatchDirs := strings.Join(helpers.UniqueStrings(helpers.ExtractRootPaths(watchDirs)), ",") + + jww.FEEDBACK.Printf("Watching for changes in %s/{%s}\n", baseWatchDir, rootWatchDirs) err := NewWatcher(serverPort) if err != nil { fmt.Println(err) diff --git a/helpers/general.go b/helpers/general.go index b05c86092..eaf4e2d42 100644 --- a/helpers/general.go +++ b/helpers/general.go @@ -90,6 +90,19 @@ func FirstUpper(s string) string { return string(unicode.ToUpper(r)) + s[n:] } +// UniqueStrings returns a new slice with any duplicates removed. +func UniqueStrings(s []string) []string { + unique := make([]string, 0) + set := map[string]interface{}{} + for _, val := range s { + if _, ok := set[val]; !ok { + unique = append(unique, val) + set[val] = val + } + } + return unique +} + // ReaderToBytes takes an io.Reader argument, reads from it // and returns bytes. func ReaderToBytes(lines io.Reader) []byte { diff --git a/helpers/general_test.go b/helpers/general_test.go index b4707b91e..4d85a1299 100644 --- a/helpers/general_test.go +++ b/helpers/general_test.go @@ -164,6 +164,15 @@ func _BenchmarkReaderContains(b *testing.B) { } } +func TestUniqueStrings(t *testing.T) { + in := []string{"a", "b", "a", "b", "c", "", "a", "", "d"} + output := UniqueStrings(in) + expected := []string{"a", "b", "c", "", "d"} + if !reflect.DeepEqual(output, expected) { + t.Errorf("Expected %#v, got %#v\n", expected, output) + } +} + func TestFindAvailablePort(t *testing.T) { addr, err := FindAvailablePort() assert.Nil(t, err) diff --git a/helpers/path.go b/helpers/path.go index 018c6fecb..07d08fa69 100644 --- a/helpers/path.go +++ b/helpers/path.go @@ -450,37 +450,27 @@ func prettifyPath(in string, b filepathPathBridge) string { return b.Join(b.Dir(in), name, "index"+ext) } -// RemoveSubpaths takes a list of paths and removes everything that -// contains another path in the list as a prefix. Ignores any empty -// strings. Used mostly for logging. -// -// e.g. ["hello/world", "hello", "foo/bar", ""] -> ["hello", "foo/bar"] -func RemoveSubpaths(paths []string) []string { - a := make([]string, 0) - for _, cur := range paths { - // ignore trivial case - if cur == "" { - continue - } - - isDupe := false - for i, old := range a { - if strings.HasPrefix(cur, old) { - isDupe = true - break - } else if strings.HasPrefix(old, cur) { - a[i] = cur - isDupe = true - break +// Extract the root paths from the supplied list of paths. +// The resulting root path will not contain any file separators, but there +// may be duplicates. +// So "/content/section/" becomes "content" +func ExtractRootPaths(paths []string) []string { + r := make([]string, len(paths)) + for i, p := range paths { + root := filepath.ToSlash(p) + if strings.Contains(root, "/") { + sections := strings.Split(root, "/") + for _, section := range sections { + if section != "" { + root = section + break + } } } - - if !isDupe { - a = append(a, cur) - } + r[i] = root } + return r - return a } // FindCWD returns the current working directory from where the Hugo diff --git a/helpers/path_test.go b/helpers/path_test.go index 9534cf9c1..a1d897df9 100644 --- a/helpers/path_test.go +++ b/helpers/path_test.go @@ -625,11 +625,19 @@ func TestPrettifyPath(t *testing.T) { } -func TestRemoveSubpaths(t *testing.T) { - got := RemoveSubpaths([]string{"hello", "hello/world", "foo/bar", ""}) - expect := []string{"hello", "foo/bar"} - if !reflect.DeepEqual(got, expect) { - t.Errorf("Expected %q but got %q", expect, got) +func TestExtractRootPaths(t *testing.T) { + tests := []struct { + input []string + expected []string + }{{[]string{filepath.FromSlash("a/b"), filepath.FromSlash("a/b/c/"), "b", + filepath.FromSlash("/c/d"), filepath.FromSlash("d/"), filepath.FromSlash("//e//")}, + []string{"a", "a", "b", "c", "d", "e"}}} + + for _, test := range tests { + output := ExtractRootPaths(test.input) + if !reflect.DeepEqual(output, test.expected) { + t.Errorf("Expected %#v, got %#v\n", test.expected, output) + } } }