shithub: hugo

Download patch

ref: 558c09305e2be16953238c6c0e828f62b950e4f5
parent: b69a36140f42ec99ffa2d1e029b8b86ecf8ff929
author: John Weldon <johnweldon4@gmail.com>
date: Wed May 13 12:20:52 EDT 2020

deploy: Do not suppress .well-known/ directory

Deployments ignore directories with a leading `.`, but should not ignore
certain well known 'hidden' directories like `.well-known/`

Fixes #6691

--- a/deploy/deploy.go
+++ b/deploy/deploy.go
@@ -440,6 +440,21 @@
 	return lf.md5
 }
 
+// knownHiddenDirectory checks if the specified name is a well known
+// hidden directory.
+func knownHiddenDirectory(name string) bool {
+	var knownDirectories = []string{
+		".well-known",
+	}
+
+	for _, dir := range knownDirectories {
+		if name == dir {
+			return true
+		}
+	}
+	return false
+}
+
 // walkLocal walks the source directory and returns a flat list of files,
 // using localFile.SlashPath as the map keys.
 func walkLocal(fs afero.Fs, matchers []*matcher, include, exclude glob.Glob) (map[string]*localFile, error) {
@@ -451,7 +466,10 @@
 		if info.IsDir() {
 			// Skip hidden directories.
 			if path != "" && strings.HasPrefix(info.Name(), ".") {
-				return filepath.SkipDir
+				// Except for specific hidden directories
+				if !knownHiddenDirectory(info.Name()) {
+					return filepath.SkipDir
+				}
 			}
 			return nil
 		}
--- a/deploy/deploy_test.go
+++ b/deploy/deploy_test.go
@@ -207,6 +207,65 @@
 	}
 }
 
+func TestWalkLocal(t *testing.T) {
+	tests := map[string]struct {
+		Given  []string
+		Expect []string
+	}{
+		"Empty": {
+			Given:  []string{},
+			Expect: []string{},
+		},
+		"Normal": {
+			Given:  []string{"file.txt", "normal_dir/file.txt"},
+			Expect: []string{"file.txt", "normal_dir/file.txt"},
+		},
+		"Hidden": {
+			Given:  []string{"file.txt", ".hidden_dir/file.txt", "normal_dir/file.txt"},
+			Expect: []string{"file.txt", "normal_dir/file.txt"},
+		},
+		"Well Known": {
+			Given:  []string{"file.txt", ".hidden_dir/file.txt", ".well-known/file.txt"},
+			Expect: []string{"file.txt", ".well-known/file.txt"},
+		},
+	}
+
+	for desc, tc := range tests {
+		t.Run(desc, func(t *testing.T) {
+			fs := afero.NewMemMapFs()
+			for _, name := range tc.Given {
+				dir, _ := path.Split(name)
+				if dir != "" {
+					if err := fs.MkdirAll(dir, 0755); err != nil {
+						t.Fatal(err)
+					}
+				}
+				if fd, err := fs.Create(name); err != nil {
+					t.Fatal(err)
+				} else {
+					fd.Close()
+				}
+			}
+			if got, err := walkLocal(fs, nil, nil, nil); err != nil {
+				t.Fatal(err)
+			} else {
+				expect := map[string]interface{}{}
+				for _, path := range tc.Expect {
+					if _, ok := got[path]; !ok {
+						t.Errorf("expected %q in results, but was not found", path)
+					}
+					expect[path] = nil
+				}
+				for path := range got {
+					if _, ok := expect[path]; !ok {
+						t.Errorf("got %q in results unexpectedly", path)
+					}
+				}
+			}
+		})
+	}
+}
+
 func TestLocalFile(t *testing.T) {
 	const (
 		content = "hello world!"