/
sub_path.go
115 lines (88 loc) · 2.35 KB
/
sub_path.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// Copyright 2024 The Carvel Authors.
// SPDX-License-Identifier: Apache-2.0
package directory
import (
"fmt"
"os"
"path/filepath"
"strings"
ctlfetch "carvel.dev/vendir/pkg/vendir/fetch"
)
type SubPath struct {
subPath string
}
func NewSubPath(subPath string) SubPath {
return SubPath{subPath}
}
func (s SubPath) Extract(srcPath, dstPath string, tempArea ctlfetch.TempArea) error {
newPath, err := ctlfetch.ScopedPath(srcPath, s.subPath)
if err != nil {
return err
}
err = s.checkDirExists(newPath, srcPath)
if err != nil {
return err
}
interDstPath, err := tempArea.NewTempDir("sub-path-extract")
if err != nil {
return err
}
defer os.RemoveAll(interDstPath)
safeNewPath := filepath.Join(interDstPath, "dst")
// Move out new path into safe dst to avoid cases
// when newPath is contained within dstPath
// (since dstPath gets deleted before newPath is moved to it)
err = ctlfetch.MoveDir(newPath, safeNewPath)
if err != nil {
return err
}
return ctlfetch.MoveDir(safeNewPath, dstPath)
}
func (s SubPath) checkDirExists(path, srcPath string) error {
_, err := os.Stat(path)
if !os.IsNotExist(err) {
return nil
}
hintMsg := ""
missingPath, _ := s.findMissingDir(srcPath)
if len(missingPath) > 0 {
altDirs, _ := s.findAltDirs(srcPath, missingPath)
if len(altDirs) > 0 {
hintMsg = fmt.Sprintf(" (found other directories: %s)", strings.Join(altDirs, ", "))
}
}
return fmt.Errorf("Expected directory '%s' (subpath) to exist%s", s.subPath, hintMsg)
}
func (s SubPath) findMissingDir(srcPath string) (string, error) {
var pieces []string
for _, piece := range filepath.SplitList(s.subPath) {
pieces = append(pieces, piece)
newPath, err := ctlfetch.ScopedPath(srcPath, filepath.Join(pieces...))
if err != nil {
return "", err
}
_, err = os.Stat(newPath)
if os.IsNotExist(err) {
return filepath.Join(pieces...), nil
}
}
return "", nil
}
func (s SubPath) findAltDirs(srcPath, subPath string) ([]string, error) {
parentDirOfSubPath := filepath.Dir(subPath)
newPath, err := ctlfetch.ScopedPath(srcPath, parentDirOfSubPath)
if err != nil {
return nil, err
}
fileInfos, err := os.ReadDir(newPath)
if err != nil {
return nil, err
}
var result []string
for _, info := range fileInfos {
if info.IsDir() {
result = append(result, filepath.Join(parentDirOfSubPath, info.Name()))
}
}
return result, nil
}