Skip to content

Commit

Permalink
Add pathutil
Browse files Browse the repository at this point in the history
  • Loading branch information
ZhuGongpu committed Jul 7, 2020
1 parent 0d01be5 commit 07e86c4
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 0 deletions.
82 changes: 82 additions & 0 deletions internal/util/pathutil/pathutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// This package contains some path-relevant utilities.
package pathutil

import (
"fmt"
"os"
"path/filepath"
"strings"
)

// Rel, like path.Rel, converts a path into a relative path to directory with the knowledge of cwd.
// Cwd, which should be an absolute path, will be used if either base or path is a relative paths.
func Rel(base string, path string, cwd string) (relativePath string, err error) {
relativePath, err = filepath.Rel(base, path)

if err != nil {
// Rel returns an error if CWD is necessary to compute it. Here is a fix.
if !filepath.IsAbs(path) {
path = filepath.Join(cwd, path)
}

if !filepath.IsAbs(base) {
base = filepath.Join(cwd, base)
}

relativePath, err = filepath.Rel(base, path)
}

return
}

// Exists returns true only if path exists and is accessible.
func Exists(path string) bool {
_, err := os.Stat(path)

return !os.IsNotExist(err)
}

// IsInsideDir checks if path is within directory.
// Both path and directory have to be absolute paths.
func IsInsideDir(path string, directory string) (isInside bool, err error) {
if !filepath.IsAbs(path) {
err = fmt.Errorf(
"argument `path` (%s) is not an absolute path",
path,
)
return
}
if !filepath.IsAbs(directory) {
err = fmt.Errorf(
"argument `directory` (%s) is not an absolute path",
directory,
)
return
}

separator := string(os.PathSeparator)
// Trim the ending separator if any
directory = strings.TrimRight(directory, separator)
directoryWithSeparator := fmt.Sprintf("%s%s", directory, separator)

isInside = path == directory || strings.HasPrefix(
path,
directoryWithSeparator,
)

return
}
105 changes: 105 additions & 0 deletions internal/util/pathutil/pathutil_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pathutil

import (
"fmt"
"io/ioutil"
"os"
"path"
"testing"

"github.com/GoogleContainerTools/kpt/internal/testutil"
"gotest.tools/assert"
)

func TestRel(t *testing.T) {
base := path.Join(os.TempDir(), "kpt-path-test")
cwd := base

actual, err := Rel(base, "resources", cwd)
expected := "resources"
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)

actual, err = Rel(base, path.Join(base, "resources"), cwd)
expected = "resources"
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)

actual, err = Rel(base, "./config", cwd)
expected = "config"
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)

actual, err = Rel(base, "../some-dir", cwd)
expected = "../some-dir"
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)

actual, err = Rel(base, os.TempDir(), cwd)
expected = ".."
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)

actual, err = Rel(base, "kpt-path-test", os.TempDir())
expected = "."
testutil.AssertNoError(t, err)
assert.Equal(t, expected, actual)
}

func TestExists(t *testing.T) {
base, err := ioutil.TempDir("", "kpt-path-test")
testutil.AssertNoError(t, err)
defer os.RemoveAll(base)

assert.Equal(t, Exists(base), true)
assert.Equal(t, Exists(path.Join(base, "some-random-dir")), false)
}

func TestIsInsideDirectory(t *testing.T) {
base := path.Join(os.TempDir(), "kpt-path-test")
file := path.Join(base, "temp-file")
dirWithSamePrefix := fmt.Sprintf("%s-surfix", base)
baseWithSeparator := fmt.Sprintf(
"%s%s",
base,
string(os.PathSeparator),
)

_, err := IsInsideDir("resources", ".")
assert.Error(t, err, "argument `path` (resources) is not an absolute path")
_, err = IsInsideDir("/resources", ".")
assert.Error(t, err, "argument `directory` (.) is not an absolute path")

result, err := IsInsideDir(path.Join(base, "."), base)
assert.NilError(t, err)
assert.Equal(t, result, true)
result, err = IsInsideDir(path.Join(base, "."), baseWithSeparator)
assert.NilError(t, err)
assert.Equal(t, result, true)
result, err = IsInsideDir(file, base)
assert.NilError(t, err)
assert.Equal(t, result, true)
result, err = IsInsideDir(path.Join(base, file), baseWithSeparator)
assert.NilError(t, err)
assert.Equal(t, result, true)
result, err = IsInsideDir(path.Join(base, ".."), base)
assert.NilError(t, err)
assert.Equal(t, result, false)
result, err = IsInsideDir(dirWithSamePrefix, base)
assert.NilError(t, err)
assert.Equal(t, result, false)
}

0 comments on commit 07e86c4

Please sign in to comment.