MCPcopy Create free account
hub / github.com/coder/envbuilder / Extract

Function Extract

devcontainer/features/features.go:95–167  ·  view source on GitHub ↗

Extract unpacks the feature from the image and returns the parsed specification.

(fs billy.Filesystem, devcontainerDir, directory, reference string)

Source from the content-addressed store, hash-verified

93// Extract unpacks the feature from the image and returns the
94// parsed specification.
95func Extract(fs billy.Filesystem, devcontainerDir, directory, reference string) (*Spec, error) {
96 if strings.HasPrefix(reference, "./") {
97 if err := copy.Copy(filepath.Join(devcontainerDir, reference), directory, copy.Options{
98 PreserveTimes: true,
99 PreserveOwner: true,
100 OnSymlink: func(src string) copy.SymlinkAction {
101 return copy.Shallow
102 },
103 OnError: func(src, dest string, err error) error {
104 if err == nil {
105 return nil
106 }
107 return fmt.Errorf("copy error: %q -> %q: %w", reference, directory, err)
108 },
109 }); err != nil {
110 return nil, err
111 }
112 } else if err := extractFromImage(fs, directory, reference); err != nil {
113 return nil, err
114 }
115
116 installScriptPath := filepath.Join(directory, "install.sh")
117 _, err := fs.Stat(installScriptPath)
118 if err != nil {
119 if errors.Is(err, os.ErrNotExist) {
120 return nil, errors.New("install.sh must be in the root of the feature")
121 }
122 return nil, fmt.Errorf("stat install.sh: %w", err)
123 }
124 chmodder, ok := fs.(interface {
125 Chmod(name string, mode os.FileMode) error
126 })
127 if ok {
128 // For some reason the filesystem abstraction doesn't support chmod.
129 // https://github.com/src-d/go-billy/issues/56
130 err = chmodder.Chmod(installScriptPath, 0o755)
131 }
132 if err != nil {
133 return nil, fmt.Errorf("chmod install.sh: %w", err)
134 }
135 featureFile, err := fs.Open(filepath.Join(directory, "devcontainer-feature.json"))
136 if err != nil {
137 if errors.Is(err, os.ErrNotExist) {
138 return nil, errors.New("devcontainer-feature.json must be in the root of the feature")
139 }
140 return nil, fmt.Errorf("open devcontainer-feature.json: %w", err)
141 }
142 defer featureFile.Close()
143 featureFileBytes, err := io.ReadAll(featureFile)
144 if err != nil {
145 return nil, fmt.Errorf("read devcontainer-feature.json: %w", err)
146 }
147 standardizedFeatureFileBytes, err := hujson.Standardize(featureFileBytes)
148 if err != nil {
149 return nil, fmt.Errorf("standardize devcontainer-feature.json: %w", err)
150 }
151 var spec *Spec
152 if err := json.Unmarshal(standardizedFeatureFileBytes, &spec); err != nil {

Callers 2

compileFeaturesMethod · 0.92
TestExtractFunction · 0.92

Calls 5

extractFromImageFunction · 0.85
JoinMethod · 0.80
ChmodMethod · 0.80
CloseMethod · 0.80
StatMethod · 0.65

Tested by 1

TestExtractFunction · 0.74