Skip to content
This repository was archived by the owner on Jan 17, 2022. It is now read-only.

Commit dfe8c04

Browse files
authored
Merge pull request #21 from xcomponent/add-component
Add new component to a project
2 parents 46ded37 + 78d9b71 commit dfe8c04

10 files changed

Lines changed: 358 additions & 135 deletions

commands/add_command.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package commands
2+
3+
import (
4+
"fmt"
5+
"github.com/xcomponent/xc-cli/util"
6+
"github.com/xcomponent/xc-cli/services"
7+
"errors"
8+
"path"
9+
)
10+
11+
func NewAddCommand(os services.OsService, http services.HttpService, io services.IoService,
12+
zip services.ZipService) *AddCommand {
13+
14+
return &AddCommand{os, http, io, zip}
15+
}
16+
17+
type AddCommand struct {
18+
os services.OsService
19+
http services.HttpService
20+
io services.IoService
21+
zip services.ZipService
22+
}
23+
24+
func (command *AddCommand) Execute(projectFolder string, elementType string, elementName string, addTemplatesGithubOrg string) error {
25+
var placeholder = ""
26+
if elementType == "component" {
27+
placeholder = "NewComponent"
28+
} else {
29+
return errors.New(fmt.Sprintf("%s is not a supported element to add to the project", elementType))
30+
}
31+
32+
err := util.NewGitHubUtils(command.os, command.http, command.io, command.zip).DownloadTemplate(
33+
projectFolder, addTemplatesGithubOrg, elementType, elementName)
34+
if err != nil {
35+
return err
36+
}
37+
38+
var elementPath = path.Join(projectFolder, placeholder)
39+
40+
if elementName != "" {
41+
elementPath = path.Join(projectFolder, elementName)
42+
43+
err = command.os.Rename(path.Join(projectFolder, placeholder), elementPath)
44+
if err != nil {
45+
return err
46+
}
47+
48+
err = util.NewFileUtils(command.os, command.io).RenameAndReplaceFiles(
49+
elementPath, placeholder, elementName)
50+
51+
if err != nil {
52+
return err
53+
}
54+
}
55+
56+
fmt.Printf("Successfully added %s %s to %s.\n", elementType, elementName, elementPath)
57+
58+
return nil
59+
60+
}

commands/add_command_test.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package commands_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo"
5+
. "github.com/onsi/gomega"
6+
"io/ioutil"
7+
"github.com/xcomponent/xc-cli/commands"
8+
"os"
9+
"github.com/daniellavoie/go-shim/zipshim/fake_zip"
10+
"archive/zip"
11+
"github.com/xcomponent/xc-cli/services"
12+
"github.com/xcomponent/xc-cli/services/servicesfake"
13+
"github.com/daniellavoie/go-shim/httpshim"
14+
"path"
15+
)
16+
17+
var _ = Describe("Add", func() {
18+
var projectFolder string
19+
var addTemplatesGithubOrg string
20+
var elementType string
21+
var elementName string
22+
var err error
23+
var osFake = &servicesfake.FakeOsService{}
24+
var httpFake = &servicesfake.FakeHttpService{}
25+
var ioFake = &servicesfake.FakeIoService{}
26+
var zipFake *fake_zip.FakeZip
27+
28+
BeforeEach(func() {
29+
addTemplatesGithubOrg = "xcomponent-add-templates"
30+
elementType = "component"
31+
elementName = "test-component"
32+
33+
var osService = services.NewOsService()
34+
osFake.StatStub = osService.Stat
35+
osFake.IsNotExistStub = osService.IsNotExist
36+
osFake.MkdirAllStub = osService.MkdirAll
37+
osFake.MkdirStub = osService.Mkdir
38+
osFake.OpenStub = osService.Open
39+
osFake.OpenFileStub = osService.OpenFile
40+
osFake.CreateStub = osService.Create
41+
osFake.RenameStub = osService.Rename
42+
43+
var ioService = services.NewIoService()
44+
ioFake.CopyStub = ioService.Copy
45+
46+
zipFake = new(fake_zip.FakeZip)
47+
zipFake.OpenReaderStub = zip.OpenReader
48+
49+
var httpService = services.NewHttpService(&httpshim.HttpShim{})
50+
httpFake.GetStub = httpService.Get
51+
httpFake.GetJsonStub = httpService.GetJson
52+
53+
err = nil
54+
})
55+
56+
JustBeforeEach(func() {
57+
err = commands.NewAddCommand(
58+
osFake,
59+
httpFake,
60+
ioFake,
61+
services.NewZipService(zipFake),
62+
).Execute(projectFolder, elementType, elementName, addTemplatesGithubOrg)
63+
})
64+
65+
Context("Add component", func() {
66+
BeforeEach(func() {
67+
var tempErr error
68+
projectFolder, tempErr = ioutil.TempDir("", "add-element-test")
69+
if tempErr != nil {
70+
panic(tempErr)
71+
}
72+
})
73+
74+
It("should succeed", func() {
75+
Expect(err).ToNot(HaveOccurred())
76+
77+
elementCreated(projectFolder, elementName)
78+
})
79+
})
80+
81+
AfterEach(func() {
82+
os.RemoveAll(projectFolder)
83+
})
84+
})
85+
86+
func elementCreated(projectFolder string, elementName string) {
87+
files, err := ioutil.ReadDir(path.Join(projectFolder, elementName))
88+
Expect(err).ShouldNot(HaveOccurred())
89+
Expect(len(files)).Should(Equal(1))
90+
}

commands/command.go

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,40 +2,22 @@ package commands
22

33
import (
44
"github.com/urfave/cli"
5-
"strings"
6-
"runtime"
75
"github.com/xcomponent/xc-cli/services"
6+
"strings"
87
)
98

109
const (
1110
installConfigUrl = "https://raw.githubusercontent.com/xcomponent/xc-cli/install-config-v1/install-config.json"
1211
projectName = ""
1312

14-
githubOrg = "xcomponent-templates"
13+
projectTemplatesGithubOrg = "xcomponent-templates"
14+
addTemplatesGithubOrg = "xcomponent-add-templates"
1515
)
1616

1717
func GetCommands(os services.OsService, http services.HttpService, io services.IoService, zip services.ZipService,
18-
exec services.ExecService) ([]cli.Command) {
18+
exec services.ExecService) []cli.Command {
1919
return []cli.Command{
20-
{
21-
Name: "install",
22-
Usage: "Install XComponent",
23-
Flags: []cli.Flag{
24-
cli.BoolFlag{Name: "keep-temp-files", Usage: "Temporary files will not be cleaned."},
25-
cli.StringFlag{
26-
Name: "install-config-url",
27-
Usage: "Url for the dependencies manifest.",
28-
Value: installConfigUrl},
29-
},
30-
Action: func(c *cli.Context) error {
31-
var installCommand = InstallCommand{os: os, io: io, http: http, exec: exec}
32-
33-
return installCommand.Install(
34-
c.String("install-config-url"),
35-
runtime.GOOS,
36-
runtime.GOARCH)
37-
},
38-
},
20+
GetCliCommand(os, http, io, exec),
3921
{
4022
Name: "init",
4123
Usage: "Initialize a new XComponent project",
@@ -54,7 +36,7 @@ func GetCommands(os services.OsService, http services.HttpService, io services.I
5436
return nil
5537
}
5638

57-
var githubOrg = githubOrg
39+
var githubOrg = projectTemplatesGithubOrg
5840
var templateName = "default"
5941
if len(c.Args()) == 1 {
6042
templateArg := c.Args().Get(0)
@@ -72,9 +54,34 @@ func GetCommands(os services.OsService, http services.HttpService, io services.I
7254
return err
7355
}
7456

75-
var initCommand = InitCommand{http, io, os, zip}
57+
return NewInitCommand(http, io, os, zip).Init(workDir, githubOrg, templateName, c.String("project-name"))
58+
},
59+
},
60+
{
61+
Name: "add",
62+
Usage: "Add new element to the project",
63+
ArgsUsage: "ELEMENT-NAME",
64+
Flags: []cli.Flag{
65+
cli.StringFlag{
66+
Name: "element-type",
67+
Usage: "Element type.",
68+
Value: "component"},
69+
},
70+
Action: func(c *cli.Context) error {
71+
if len(c.Args()) != 1 {
72+
cli.ShowCommandHelp(c, "add")
73+
74+
os.Exit(1)
75+
return nil
76+
}
77+
78+
workDir, err := os.Getwd()
79+
if err != nil {
80+
return err
81+
}
7682

77-
return initCommand.Init(workDir, githubOrg, templateName, c.String("project-name"))
83+
return NewAddCommand(os, http, io, zip).Execute(workDir, c.String("element-type"), c.Args().Get(0),
84+
addTemplatesGithubOrg)
7885
},
7986
},
8087
}

commands/command_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ var _ = Describe("Config", func() {
2020
services.NewExecService(new(execshim.ExecShim)))
2121

2222
Expect(commands).ShouldNot(BeNil())
23-
Expect(len(commands)).Should(Equal(2))
23+
Expect(len(commands)).Should(Equal(3))
2424
})
2525
})

commands/init_command.go

Lines changed: 10 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
package commands
22

33
import (
4-
. "os"
54
"fmt"
65
"errors"
7-
"path/filepath"
8-
"strings"
96
"github.com/xcomponent/xc-cli/services"
107
"io"
11-
"archive/zip"
128
"github.com/xcomponent/xc-cli/util"
139
)
1410

@@ -33,23 +29,24 @@ func (initCommand *InitCommand) Init(
3329
return err
3430
}
3531

36-
fileName, err := initCommand.downloadTemplate(projectFolder, githubOrg, templateName)
37-
defer initCommand.clean(fileName)
38-
39-
if err != nil {
40-
return err
41-
}
42-
43-
err = initCommand.unzip(fileName, projectFolder)
32+
err = util.NewGitHubUtils(initCommand.os, initCommand.http, initCommand.io, initCommand.zip).DownloadTemplate(
33+
projectFolder, githubOrg, templateName, projectName)
4434
if err != nil {
4535
return err
4636
}
4737

4838
if projectName != "" {
49-
return util.NewFileUtils(initCommand.os, initCommand.io).RenameAndReplaceFiles(
39+
err = util.NewFileUtils(initCommand.os, initCommand.io).RenameAndReplaceFiles(
5040
projectFolder, "NewProject", projectName)
41+
if err != nil {
42+
return err
43+
}
44+
}else {
45+
projectName = "NewProject"
5146
}
5247

48+
fmt.Printf("Successfully initialized project %s in %s.\n", projectName,projectFolder)
49+
5350
return nil
5451
}
5552

@@ -90,92 +87,3 @@ func (initCommand *InitCommand) isEmpty(name string) (bool, error) {
9087
}
9188
return false, err // Either not empty or error, suits both cases
9289
}
93-
94-
func (initCommand *InitCommand) downloadTemplate(projectFolder string, githubOrg string, templateName string) (string, error) {
95-
fmt.Println("Downloading template")
96-
97-
fileName := fmt.Sprintf("%s/%s.zip", projectFolder, templateName)
98-
99-
out, err := initCommand.os.Create(fileName)
100-
defer out.Close()
101-
if err != nil {
102-
return fileName, err
103-
}
104-
105-
resp, err := initCommand.http.Get(fmt.Sprintf("https://github.com/%s/%s/archive/master.zip", githubOrg, templateName))
106-
if resp != nil {
107-
defer resp.Body.Close()
108-
}
109-
if err != nil {
110-
return fileName, err
111-
}
112-
113-
if resp.StatusCode == 404 {
114-
return fileName, errors.New(fmt.Sprintf("Project template %s/%s could not be found", githubOrg, templateName))
115-
}
116-
117-
_, err = initCommand.io.Copy(out, resp.Body)
118-
if err != nil {
119-
return fileName, err
120-
}
121-
122-
return fileName, nil
123-
}
124-
125-
func (initCommand *InitCommand) unzip(archive string, target string) error {
126-
fmt.Println(fmt.Sprintf("Extracting template from %s", archive))
127-
128-
reader, err := initCommand.zip.OpenReader(archive)
129-
if err != nil {
130-
return err
131-
}
132-
133-
if err := initCommand.os.MkdirAll(target, 0755); err != nil {
134-
return err
135-
}
136-
137-
for _, file := range reader.File {
138-
err = initCommand.unzipFile(file, target)
139-
if err != nil {
140-
return err
141-
}
142-
}
143-
144-
return nil
145-
}
146-
147-
func (initCommand *InitCommand) unzipFile(file *zip.File, target string) error {
148-
fileName := file.Name[strings.Index(file.Name, "/")+1:len(file.Name)]
149-
150-
path := filepath.Join(target, fileName)
151-
if file.FileInfo().IsDir() {
152-
initCommand.os.MkdirAll(path, file.Mode())
153-
return nil
154-
}
155-
156-
fileReader, err := file.Open()
157-
if err != nil {
158-
return err
159-
}
160-
defer fileReader.Close()
161-
162-
targetFile, err := initCommand.os.OpenFile(path, O_WRONLY|O_CREATE|O_TRUNC, file.Mode())
163-
if targetFile != nil {
164-
defer targetFile.Close()
165-
}
166-
if err != nil {
167-
return err
168-
}
169-
170-
if _, err := initCommand.io.Copy(targetFile, fileReader); err != nil {
171-
return err
172-
}
173-
174-
return nil
175-
}
176-
177-
func (initCommand *InitCommand) clean(fileName string) error {
178-
fmt.Println(fmt.Sprintf("Cleaning %s", fileName))
179-
180-
return initCommand.os.Remove(fileName)
181-
}

0 commit comments

Comments
 (0)