...
1
16
17 package cp
18
19 import (
20 "path"
21 "path/filepath"
22 "strings"
23 )
24
25 type fileSpec struct {
26 PodName string
27 PodNamespace string
28 File pathSpec
29 }
30
31 type pathSpec interface {
32 String() string
33 }
34
35
36
37
38 type localPath struct {
39 file string
40 }
41
42 func newLocalPath(fileName string) localPath {
43 file := stripTrailingSlash(fileName)
44 return localPath{file: file}
45 }
46
47 func (p localPath) String() string {
48 return p.file
49 }
50
51 func (p localPath) Dir() localPath {
52 return newLocalPath(filepath.Dir(p.file))
53 }
54
55 func (p localPath) Base() localPath {
56 return newLocalPath(filepath.Base(p.file))
57 }
58
59 func (p localPath) Clean() localPath {
60 return newLocalPath(filepath.Clean(p.file))
61 }
62
63 func (p localPath) Join(elem pathSpec) localPath {
64 return newLocalPath(filepath.Join(p.file, elem.String()))
65 }
66
67 func (p localPath) Glob() (matches []string, err error) {
68 return filepath.Glob(p.file)
69 }
70
71 func (p localPath) StripSlashes() localPath {
72 return newLocalPath(stripLeadingSlash(p.file))
73 }
74
75 func isRelative(base, target localPath) bool {
76 relative, err := filepath.Rel(base.String(), target.String())
77 if err != nil {
78 return false
79 }
80 return relative == "." || relative == stripPathShortcuts(relative)
81 }
82
83
84
85 type remotePath struct {
86 file string
87 }
88
89 func newRemotePath(fileName string) remotePath {
90
91
92 file := strings.ReplaceAll(stripTrailingSlash(fileName), `\`, "/")
93 return remotePath{file: file}
94 }
95
96 func (p remotePath) String() string {
97 return p.file
98 }
99
100 func (p remotePath) Dir() remotePath {
101 return newRemotePath(path.Dir(p.file))
102 }
103
104 func (p remotePath) Base() remotePath {
105 return newRemotePath(path.Base(p.file))
106 }
107
108 func (p remotePath) Clean() remotePath {
109 return newRemotePath(path.Clean(p.file))
110 }
111
112 func (p remotePath) Join(elem pathSpec) remotePath {
113 return newRemotePath(path.Join(p.file, elem.String()))
114 }
115
116 func (p remotePath) StripShortcuts() remotePath {
117 p = p.Clean()
118 return newRemotePath(stripPathShortcuts(p.file))
119 }
120
121 func (p remotePath) StripSlashes() remotePath {
122 return newRemotePath(stripLeadingSlash(p.file))
123 }
124
125
126 func stripTrailingSlash(file string) string {
127 if len(file) == 0 {
128 return file
129 }
130 if file != "/" && strings.HasSuffix(string(file[len(file)-1]), "/") {
131 return file[:len(file)-1]
132 }
133 return file
134 }
135
136 func stripLeadingSlash(file string) string {
137
138 return strings.TrimLeft(file, `/\`)
139 }
140
141
142 func stripPathShortcuts(p string) string {
143 newPath := p
144 trimmed := strings.TrimPrefix(newPath, "../")
145
146 for trimmed != newPath {
147 newPath = trimmed
148 trimmed = strings.TrimPrefix(newPath, "../")
149 }
150
151
152 if newPath == "." || newPath == ".." {
153 newPath = ""
154 }
155
156 if len(newPath) > 0 && string(newPath[0]) == "/" {
157 return newPath[1:]
158 }
159
160 return newPath
161 }
162
View as plain text