update resolveSymlinkAncestor and add tests
This commit is contained in:
		
							parent
							
								
									a675ad998a
								
							
						
					
					
						commit
						01f6aba517
					
				|  | @ -125,8 +125,10 @@ func resolveSymlinkAncestor(path string) (string, error) { | ||||||
| 	if !filepath.IsAbs(path) { | 	if !filepath.IsAbs(path) { | ||||||
| 		return "", errors.New("dest path must be abs") | 		return "", errors.New("dest path must be abs") | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	last := "" | 	last := "" | ||||||
| 	newPath := path | 	newPath := path | ||||||
|  | 
 | ||||||
| loop: | loop: | ||||||
| 	for newPath != "/" { | 	for newPath != "/" { | ||||||
| 		fi, err := os.Lstat(newPath) | 		fi, err := os.Lstat(newPath) | ||||||
|  | @ -134,11 +136,15 @@ loop: | ||||||
| 			return "", errors.Wrap(err, "failed to lstat") | 			return "", errors.Wrap(err, "failed to lstat") | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		switch mode := fi.Mode(); { | 		if util.IsSymlink(fi) { | ||||||
| 		case mode&os.ModeSymlink != 0: |  | ||||||
| 			last = filepath.Base(newPath) | 			last = filepath.Base(newPath) | ||||||
| 			newPath = filepath.Dir(newPath) | 			newPath = filepath.Dir(newPath) | ||||||
| 		default: | 		} else { | ||||||
|  | 			// Even if the filenode pointed to by newPath is a regular file,
 | ||||||
|  | 			// one of its ancestors could be a symlink. We call filepath.EvalSymlinks
 | ||||||
|  | 			// to test whether there are any links in the path. If the output of
 | ||||||
|  | 			// EvalSymlinks is different than the input we know one of the nodes in the
 | ||||||
|  | 			// the path is a link.
 | ||||||
| 			target, err := filepath.EvalSymlinks(newPath) | 			target, err := filepath.EvalSymlinks(newPath) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				return "", err | 				return "", err | ||||||
|  |  | ||||||
|  | @ -183,3 +183,196 @@ func Test_ResolvePaths(t *testing.T) { | ||||||
| 		validateResults(t, files, expectedFiles, err) | 		validateResults(t, files, expectedFiles, err) | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func Test_resolveSymlinkAncestor(t *testing.T) { | ||||||
|  | 	setupDirs := func(t *testing.T) (string, string) { | ||||||
|  | 		testDir, err := ioutil.TempDir("", "") | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		targetDir := filepath.Join(testDir, "bar", "baz") | ||||||
|  | 
 | ||||||
|  | 		if err := os.MkdirAll(targetDir, 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		targetPath := filepath.Join(targetDir, "bam.txt") | ||||||
|  | 
 | ||||||
|  | 		if err := ioutil.WriteFile(targetPath, []byte("meow"), 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		return testDir, targetPath | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	t.Run("path is a symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		linkDir := filepath.Join(testDir, "foo", "buzz") | ||||||
|  | 
 | ||||||
|  | 		if err := os.MkdirAll(linkDir, 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkPath := filepath.Join(linkDir, "zoom.txt") | ||||||
|  | 
 | ||||||
|  | 		if err := os.Symlink(targetPath, linkPath); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		expected := linkPath | ||||||
|  | 
 | ||||||
|  | 		actual, err := resolveSymlinkAncestor(linkPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("expected err to be nil but was %s", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if actual != expected { | ||||||
|  | 			t.Errorf("expected result to be %s not %s", expected, actual) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("path is a dead symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		linkDir := filepath.Join(testDir, "foo", "buzz") | ||||||
|  | 
 | ||||||
|  | 		if err := os.MkdirAll(linkDir, 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkPath := filepath.Join(linkDir, "zoom.txt") | ||||||
|  | 
 | ||||||
|  | 		if err := os.Symlink(targetPath, linkPath); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := os.Remove(targetPath); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		expected := linkPath | ||||||
|  | 
 | ||||||
|  | 		actual, err := resolveSymlinkAncestor(linkPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("expected err to be nil but was %s", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if actual != expected { | ||||||
|  | 			t.Errorf("expected result to be %s not %s", expected, actual) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("path is not a symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		expected := targetPath | ||||||
|  | 
 | ||||||
|  | 		actual, err := resolveSymlinkAncestor(targetPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("expected err to be nil but was %s", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if actual != expected { | ||||||
|  | 			t.Errorf("expected result to be %s not %s", expected, actual) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("parent of path is a symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		targetDir := filepath.Dir(targetPath) | ||||||
|  | 
 | ||||||
|  | 		linkDir := filepath.Join(testDir, "foo") | ||||||
|  | 
 | ||||||
|  | 		if err := os.MkdirAll(linkDir, 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkDir = filepath.Join(linkDir, "gaz") | ||||||
|  | 
 | ||||||
|  | 		if err := os.Symlink(targetDir, linkDir); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkPath := filepath.Join(linkDir, filepath.Base(targetPath)) | ||||||
|  | 
 | ||||||
|  | 		expected := linkDir | ||||||
|  | 
 | ||||||
|  | 		actual, err := resolveSymlinkAncestor(linkPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("expected err to be nil but was %s", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if actual != expected { | ||||||
|  | 			t.Errorf("expected result to be %s not %s", expected, actual) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("parent of path is a dead symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		targetDir := filepath.Dir(targetPath) | ||||||
|  | 
 | ||||||
|  | 		linkDir := filepath.Join(testDir, "foo") | ||||||
|  | 
 | ||||||
|  | 		if err := os.MkdirAll(linkDir, 0777); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkDir = filepath.Join(linkDir, "gaz") | ||||||
|  | 
 | ||||||
|  | 		if err := os.Symlink(targetDir, linkDir); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err := os.RemoveAll(targetDir); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkPath := filepath.Join(linkDir, filepath.Base(targetPath)) | ||||||
|  | 
 | ||||||
|  | 		_, err := resolveSymlinkAncestor(linkPath) | ||||||
|  | 		if err == nil { | ||||||
|  | 			t.Error("expected err to not be nil") | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("great grandparent of path is a symlink", func(t *testing.T) { | ||||||
|  | 		testDir, targetPath := setupDirs(t) | ||||||
|  | 		defer os.RemoveAll(testDir) | ||||||
|  | 
 | ||||||
|  | 		targetDir := filepath.Dir(targetPath) | ||||||
|  | 
 | ||||||
|  | 		linkDir := filepath.Join(testDir, "foo") | ||||||
|  | 
 | ||||||
|  | 		if err := os.Symlink(filepath.Dir(targetDir), linkDir); err != nil { | ||||||
|  | 			t.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		linkPath := filepath.Join( | ||||||
|  | 			linkDir, | ||||||
|  | 			filepath.Join( | ||||||
|  | 				filepath.Base(targetDir), | ||||||
|  | 				filepath.Base(targetPath), | ||||||
|  | 			), | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		expected := linkDir | ||||||
|  | 
 | ||||||
|  | 		actual, err := resolveSymlinkAncestor(linkPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			t.Errorf("expected err to be nil but was %s", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if actual != expected { | ||||||
|  | 			t.Errorf("expected result to be %s not %s", expected, actual) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue