Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / github.com / go-openapi / spec / normalizer.go
1 // Copyright 2015 go-swagger maintainers
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package spec
16
17 import (
18         "fmt"
19         "net/url"
20         "os"
21         "path"
22         "path/filepath"
23         "strings"
24 )
25
26 // normalize absolute path for cache.
27 // on Windows, drive letters should be converted to lower as scheme in net/url.URL
28 func normalizeAbsPath(path string) string {
29         u, err := url.Parse(path)
30         if err != nil {
31                 debugLog("normalize absolute path failed: %s", err)
32                 return path
33         }
34         return u.String()
35 }
36
37 // base or refPath could be a file path or a URL
38 // given a base absolute path and a ref path, return the absolute path of refPath
39 // 1) if refPath is absolute, return it
40 // 2) if refPath is relative, join it with basePath keeping the scheme, hosts, and ports if exists
41 // base could be a directory or a full file path
42 func normalizePaths(refPath, base string) string {
43         refURL, _ := url.Parse(refPath)
44         if path.IsAbs(refURL.Path) || filepath.IsAbs(refPath) {
45                 // refPath is actually absolute
46                 if refURL.Host != "" {
47                         return refPath
48                 }
49                 parts := strings.Split(refPath, "#")
50                 result := filepath.FromSlash(parts[0])
51                 if len(parts) == 2 {
52                         result += "#" + parts[1]
53                 }
54                 return result
55         }
56
57         // relative refPath
58         baseURL, _ := url.Parse(base)
59         if !strings.HasPrefix(refPath, "#") {
60                 // combining paths
61                 if baseURL.Host != "" {
62                         baseURL.Path = path.Join(path.Dir(baseURL.Path), refURL.Path)
63                 } else { // base is a file
64                         newBase := fmt.Sprintf("%s#%s", filepath.Join(filepath.Dir(base), filepath.FromSlash(refURL.Path)), refURL.Fragment)
65                         return newBase
66                 }
67
68         }
69         // copying fragment from ref to base
70         baseURL.Fragment = refURL.Fragment
71         return baseURL.String()
72 }
73
74 // denormalizePaths returns to simplest notation on file $ref,
75 // i.e. strips the absolute path and sets a path relative to the base path.
76 //
77 // This is currently used when we rewrite ref after a circular ref has been detected
78 func denormalizeFileRef(ref *Ref, relativeBase, originalRelativeBase string) *Ref {
79         debugLog("denormalizeFileRef for: %s", ref.String())
80
81         if ref.String() == "" || ref.IsRoot() || ref.HasFragmentOnly {
82                 return ref
83         }
84         // strip relativeBase from URI
85         relativeBaseURL, _ := url.Parse(relativeBase)
86         relativeBaseURL.Fragment = ""
87
88         if relativeBaseURL.IsAbs() && strings.HasPrefix(ref.String(), relativeBase) {
89                 // this should work for absolute URI (e.g. http://...): we have an exact match, just trim prefix
90                 r, _ := NewRef(strings.TrimPrefix(ref.String(), relativeBase))
91                 return &r
92         }
93
94         if relativeBaseURL.IsAbs() {
95                 // other absolute URL get unchanged (i.e. with a non-empty scheme)
96                 return ref
97         }
98
99         // for relative file URIs:
100         originalRelativeBaseURL, _ := url.Parse(originalRelativeBase)
101         originalRelativeBaseURL.Fragment = ""
102         if strings.HasPrefix(ref.String(), originalRelativeBaseURL.String()) {
103                 // the resulting ref is in the expanded spec: return a local ref
104                 r, _ := NewRef(strings.TrimPrefix(ref.String(), originalRelativeBaseURL.String()))
105                 return &r
106         }
107
108         // check if we may set a relative path, considering the original base path for this spec.
109         // Example:
110         //   spec is located at /mypath/spec.json
111         //   my normalized ref points to: /mypath/item.json#/target
112         //   expected result: item.json#/target
113         parts := strings.Split(ref.String(), "#")
114         relativePath, err := filepath.Rel(path.Dir(originalRelativeBaseURL.String()), parts[0])
115         if err != nil {
116                 // there is no common ancestor (e.g. different drives on windows)
117                 // leaves the ref unchanged
118                 return ref
119         }
120         if len(parts) == 2 {
121                 relativePath += "#" + parts[1]
122         }
123         r, _ := NewRef(relativePath)
124         return &r
125 }
126
127 // relativeBase could be an ABSOLUTE file path or an ABSOLUTE URL
128 func normalizeFileRef(ref *Ref, relativeBase string) *Ref {
129         // This is important for when the reference is pointing to the root schema
130         if ref.String() == "" {
131                 r, _ := NewRef(relativeBase)
132                 return &r
133         }
134
135         debugLog("normalizing %s against %s", ref.String(), relativeBase)
136
137         s := normalizePaths(ref.String(), relativeBase)
138         r, _ := NewRef(s)
139         return &r
140 }
141
142 // absPath returns the absolute path of a file
143 func absPath(fname string) (string, error) {
144         if strings.HasPrefix(fname, "http") {
145                 return fname, nil
146         }
147         if filepath.IsAbs(fname) {
148                 return fname, nil
149         }
150         wd, err := os.Getwd()
151         return filepath.Join(wd, fname), err
152 }