Skip to content

Commit 59af8f3

Browse files
committed
Add 'template add-link' command
1 parent a4b4d7b commit 59af8f3

File tree

2 files changed

+86
-2
lines changed

2 files changed

+86
-2
lines changed

cmd/devcontainer/template.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"fmt"
5+
"io/ioutil"
56
"os"
67
"sort"
78

@@ -18,6 +19,7 @@ func createTemplateCommand() *cobra.Command {
1819
}
1920
cmd.AddCommand(createTemplateListCommand())
2021
cmd.AddCommand(createTemplateAddCommand())
22+
cmd.AddCommand(createTemplateAddLinkCommand())
2123
return cmd
2224
}
2325

@@ -100,3 +102,67 @@ func createTemplateAddCommand() *cobra.Command {
100102
}
101103
return cmd
102104
}
105+
106+
func createTemplateAddLinkCommand() *cobra.Command {
107+
cmd := &cobra.Command{
108+
Use: "add-link TEMPLATE_NAME",
109+
Short: "add-link devcontainer from template",
110+
Long: "Symlink a devcontainer definition to the current folder using the specified template",
111+
Run: func(cmd *cobra.Command, args []string) {
112+
113+
if len(args) != 1 {
114+
cmd.Usage()
115+
os.Exit(1)
116+
}
117+
name := args[0]
118+
119+
template, err := devcontainers.GetTemplateByName(name)
120+
if err != nil {
121+
fmt.Println(err)
122+
os.Exit(1)
123+
}
124+
if template == nil {
125+
fmt.Printf("Template '%s' not found\n", name)
126+
}
127+
128+
info, err := os.Stat("./.devcontainer")
129+
if info != nil && err == nil {
130+
fmt.Println("Current folder already contains a .devcontainer folder - exiting")
131+
os.Exit(1)
132+
}
133+
134+
currentDirectory, err := os.Getwd()
135+
if err != nil {
136+
fmt.Printf("Error reading current directory: %s\n", err)
137+
}
138+
if err = ioutil2.LinkFolder(template.Path, currentDirectory+"/.devcontainer"); err != nil {
139+
fmt.Printf("Error linking folder: %s\n", err)
140+
os.Exit(1)
141+
}
142+
143+
content := []byte("*\n")
144+
if err := ioutil.WriteFile(currentDirectory+"/.devcontainer/.gitignore", content, 0644); err != nil { // -rw-r--r--
145+
fmt.Printf("Error writing .gitignore: %s\n", err)
146+
os.Exit(1)
147+
}
148+
},
149+
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
150+
// only completing the first arg (template name)
151+
if len(args) != 0 {
152+
return nil, cobra.ShellCompDirectiveNoFileComp
153+
}
154+
templates, err := devcontainers.GetTemplates()
155+
if err != nil {
156+
fmt.Printf("Error: %v", err)
157+
os.Exit(1)
158+
}
159+
names := []string{}
160+
for _, template := range templates {
161+
names = append(names, template.Name)
162+
}
163+
sort.Strings(names)
164+
return names, cobra.ShellCompDirectiveNoFileComp
165+
},
166+
}
167+
return cmd
168+
}

internal/pkg/ioutil/files.go

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,19 @@ import (
1010
// TODO - recursive copy folder (also add recursive symlink)
1111

1212
func CopyFolder(source string, target string) error {
13+
copy := func(sourceFolder string, targetFolder string, item os.FileInfo) error {
14+
return CopyFile(sourceFolder+"/"+item.Name(), targetFolder+"/"+item.Name(), item.Mode())
15+
}
16+
return processFolder(source, target, copy)
17+
}
18+
func LinkFolder(source string, target string) error {
19+
symlink := func(sourceFolder string, targetFolder string, item os.FileInfo) error {
20+
return os.Symlink(sourceFolder+"/"+item.Name(), targetFolder+"/"+item.Name())
21+
}
22+
return processFolder(source, target, symlink)
23+
}
24+
25+
func processFolder(source string, target string, fileHandler func(sourceFolder string, targetFolder string, item os.FileInfo) error) error {
1326
sourceItem, err := os.Stat(source)
1427
if err != nil {
1528
return fmt.Errorf("Error reading source folder: %s\n", err)
@@ -25,13 +38,18 @@ func CopyFolder(source string, target string) error {
2538

2639
for _, sourceSubItem := range sourceSubItems {
2740
if sourceSubItem.IsDir() {
28-
CopyFolder(source+"/"+sourceSubItem.Name(), target+"/"+sourceSubItem.Name())
41+
if err = processFolder(source+"/"+sourceSubItem.Name(), target+"/"+sourceSubItem.Name(), fileHandler); err != nil {
42+
return err
43+
}
2944
} else {
30-
CopyFile(source+"/"+sourceSubItem.Name(), target+"/"+sourceSubItem.Name(), sourceSubItem.Mode())
45+
if err = fileHandler(source, target, sourceSubItem); err != nil {
46+
return err
47+
}
3148
}
3249
}
3350
return nil
3451
}
52+
3553
func CopyFile(source string, target string, perm os.FileMode) error {
3654
sourceFile, err := os.Open(source)
3755
if err != nil {

0 commit comments

Comments
 (0)