Skip to content

Commit 958592a

Browse files
committed
Handle substitution for templates
1 parent 0f3706a commit 958592a

File tree

5 files changed

+269
-29
lines changed

5 files changed

+269
-29
lines changed

docs/template.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,20 @@ Assuming you cloned [github.com/microsoft/vscode-dev-containers/](https://github
8282
}
8383
```
8484

85+
## Placeholder Values
86+
87+
After content has been copied to the project folder from a template, the following placeholder values are substituted:
88+
89+
| Placeholder | Value |
90+
|------------------------------|----------------------------------------------------------------------------------------------------------------------|
91+
| `__DEVCONTAINER_NAME__` | The name of the dev container (from the `name` property in `devcontainer.json`) |
92+
| `__DEVCONTAINER_USER_NAME__` | The name of the user for dev container (from the `remoteuser` property in `devcontainer.json`, or `root` if not set) |
93+
| `__DEVCONTAINER_HOME__` | The home folder for the dev container (e.g. `/home/vscode` or `/root`) |
94+
8595
## Repository containers
8696

8797
VS Code dev containers have another feature called "Repository containers". These are a set of dev container definitions that VS Code will automatically apply to a project based on its git repo.
8898

8999
The default definitions are in the [microsoft/vscode-dev-containers](https://github.com/microsoft/vscode-dev-containers/tree/master/repository-containers) repo. If you look at the repo, you will see a `github.com` folder followed by paths for `<org>/<repo>`, e.g. `django/django`. The `https://github.com/django/django` repo doesn't contain a dev container definition, but VS Code will use the repository container definition from the `microsoft/vscode-dev-containers` repo.
90100

91-
You can also configure VS Code to look for additional local paths for repository containers by providing a value for the VS Code `remote.containers.repository-container-paths` setting (see [this issue](https://github.com/microsoft/vscode-remote-release/issues/3218) for more details).
92-
101+
You can also configure VS Code to look for additional local paths for repository containers by providing a value for the VS Code `remote.containers.repository-container-paths` setting (see [this issue](https://github.com/microsoft/vscode-remote-release/issues/3218) for more details).

internal/pkg/devcontainers/snippet.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,17 @@ func getSubstitutionValuesFromFile(devContainerJsonPath string) (*SubstitutionVa
407407
}, nil
408408
}
409409

410+
func performSubstitutionFile(substitutionValues *SubstitutionValues, filename string) error {
411+
buf, err := ioutil.ReadFile(filename)
412+
if err != nil {
413+
return err
414+
}
415+
content := string(buf)
416+
content = performSubstitutionString(substitutionValues, content)
417+
err = ioutil.WriteFile(filename, []byte(content), 0)
418+
return err
419+
}
420+
410421
func performSubstitutionString(substitutionValues *SubstitutionValues, content string) string {
411422
// replace __DEVCONTAINER_NAME__ with name etc
412423
content = strings.ReplaceAll(content, "__DEVCONTAINER_NAME__", substitutionValues.Name)

internal/pkg/devcontainers/template.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func GetDefaultDevcontainerNameForFolder(folderPath string) (string, error) {
113113
func CopyTemplateToFolder(templatePath string, targetFolder string, devcontainerName string) error {
114114
var err error
115115

116-
if err = ioutil2.CopyFolder(templatePath, targetFolder+"/.devcontainer"); err != nil {
116+
if err = ioutil2.CopyFolder(templatePath, filepath.Join(targetFolder, ".devcontainer")); err != nil {
117117
return fmt.Errorf("Error copying folder: %s\n", err)
118118
}
119119

@@ -125,12 +125,46 @@ func CopyTemplateToFolder(templatePath string, targetFolder string, devcontainer
125125
return fmt.Errorf("Error getting default devcontainer name: %s", err)
126126
}
127127
}
128-
devcontainerJsonPath := filepath.Join(targetFolder, ".devcontainer/devcontainer.json")
128+
devcontainerJsonPath := filepath.Join(targetFolder, ".devcontainer", "devcontainer.json")
129129
err = SetDevcontainerName(devcontainerJsonPath, devcontainerName)
130130
if err != nil {
131131
return fmt.Errorf("Error setting devcontainer name: %s", err)
132132
}
133133

134+
values, err := getSubstitutionValuesFromFile(devcontainerJsonPath)
135+
if err != nil {
136+
return fmt.Errorf("Error getting substituion values: %s", err)
137+
}
138+
err = recursiveSubstituteValues(values, filepath.Join(targetFolder, ".devcontainer"))
139+
if err != nil {
140+
return fmt.Errorf("Error performing substitution: %s", err)
141+
}
142+
143+
return nil
144+
}
145+
146+
func recursiveSubstituteValues(values *SubstitutionValues, path string) error {
147+
_, err := os.Stat(path)
148+
if err != nil {
149+
return fmt.Errorf("Error reading folder: %s\n", err)
150+
}
151+
152+
subItems, err := ioutil.ReadDir(path)
153+
if err != nil {
154+
return fmt.Errorf("Error reading source folder contents: %s\n", err)
155+
}
156+
157+
for _, subItem := range subItems {
158+
if subItem.IsDir() {
159+
if err = recursiveSubstituteValues(values, filepath.Join(path, subItem.Name())); err != nil {
160+
return err
161+
}
162+
} else {
163+
if err = performSubstitutionFile(values, filepath.Join(path, subItem.Name())); err != nil {
164+
return err
165+
}
166+
}
167+
}
134168
return nil
135169
}
136170

0 commit comments

Comments
 (0)