1 package registry
2
3 import (
4 "errors"
5 "fmt"
6 "os"
7 "path/filepath"
8
9 "github.com/redhat-developer/odo/pkg/testingutil/filesystem"
10
11 devfilev1 "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
12 parsercommon "github.com/devfile/library/v2/pkg/devfile/parser/data/v2/common"
13 "github.com/go-git/go-git/v5"
14 "github.com/go-git/go-git/v5/plumbing"
15 "github.com/go-git/go-git/v5/plumbing/transport/http"
16
17 "github.com/redhat-developer/odo/pkg/devfile/location"
18 "github.com/redhat-developer/odo/pkg/log"
19 "github.com/redhat-developer/odo/pkg/util"
20 )
21
22 const (
23 RegistryUser = "default"
24 )
25
26 func checkoutProject(subDir, zipURL, path, starterToken string, fsys filesystem.Filesystem) error {
27
28 if subDir == "" {
29 subDir = "/"
30 }
31 err := util.GetAndExtractZip(zipURL, path, subDir, starterToken, fsys)
32 if err != nil {
33 return fmt.Errorf("failed to download and extract project zip folder: %w", err)
34 }
35 return nil
36 }
37
38
39
40 func DownloadStarterProject(fs filesystem.Filesystem, starterProject *devfilev1.StarterProject, decryptedToken string, contextDir string, verbose bool) error {
41 var path string
42 var err error
43
44 if contextDir == "" {
45 path, err = os.Getwd()
46 if err != nil {
47 return fmt.Errorf("could not get the current working directory: %w", err)
48 }
49 } else {
50 path = contextDir
51 }
52
53
54 err = util.IsValidProjectDir(path, location.DevfileLocation(fs, ""), fs)
55 if err != nil {
56 return err
57 }
58
59 if verbose {
60 log.Info("\nStarter Project")
61 }
62
63 if starterProject.Git != nil {
64 err := downloadGitProject(starterProject, decryptedToken, path, verbose)
65
66 if err != nil {
67 return err
68 }
69
70 } else if starterProject.Zip != nil {
71 url := starterProject.Zip.Location
72 sparseDir := starterProject.SubDir
73 var downloadSpinner *log.Status
74 if verbose {
75 downloadSpinner = log.Spinnerf("Downloading starter project %s from %s", starterProject.Name, url)
76 }
77 err := checkoutProject(sparseDir, url, path, decryptedToken, fs)
78 if err != nil {
79 if verbose {
80 downloadSpinner.End(false)
81 }
82 return err
83 }
84 if verbose {
85 downloadSpinner.End(true)
86 }
87 } else {
88 return errors.New("project type not supported")
89 }
90
91 return nil
92 }
93
94
95 func downloadGitProject(starterProject *devfilev1.StarterProject, starterToken, path string, verbose bool) error {
96 remoteName, remoteUrl, revision, err := parsercommon.GetDefaultSource(starterProject.Git.GitLikeProjectSource)
97 if err != nil {
98 return fmt.Errorf("unable to get default project source for starter project %s: %w", starterProject.Name, err)
99 }
100
101
102
103 refName := plumbing.ReferenceName(revision)
104
105 if plumbing.IsHash(revision) {
106
107
108 log.Warning("Specifying commit in 'revision' is not yet supported in odo.")
109
110 revision = ""
111 }
112
113 if revision != "" {
114
115 refName = plumbing.NewBranchReferenceName(revision)
116 }
117
118 var downloadSpinner *log.Status
119 if verbose {
120 downloadSpinner = log.Spinnerf("Downloading starter project %s from %s", starterProject.Name, remoteUrl)
121 defer downloadSpinner.End(false)
122 }
123
124 cloneOptions := &git.CloneOptions{
125 URL: remoteUrl,
126 RemoteName: remoteName,
127
128 Depth: 1,
129 }
130
131 if refName != "" {
132 cloneOptions.ReferenceName = refName
133 cloneOptions.SingleBranch = true
134
135 }
136
137 if starterToken != "" {
138 cloneOptions.Auth = &http.BasicAuth{
139 Username: RegistryUser,
140 Password: starterToken,
141 }
142 }
143
144 originalPath := ""
145 if starterProject.SubDir != "" {
146 originalPath = path
147 path, err = os.MkdirTemp("", "")
148 if err != nil {
149 return err
150 }
151 }
152
153 _, err = git.PlainClone(path, false, cloneOptions)
154
155 if err != nil {
156
157
158
159 if _, ok := err.(git.NoMatchingRefSpecError); !ok || revision == "" {
160 return err
161 }
162
163
164 cloneOptions.ReferenceName = plumbing.NewTagReferenceName(revision)
165
166 _ = os.RemoveAll(filepath.Join(path, ".git"))
167 _, err = git.PlainClone(path, false, cloneOptions)
168 if err != nil {
169 return err
170 }
171 }
172
173
174 err = os.RemoveAll(filepath.Join(path, ".git"))
175 if err != nil {
176
177 log.Warning("Unable to delete .git from cloned starter project")
178 }
179
180 if starterProject.SubDir != "" {
181 err = util.GitSubDir(path, originalPath,
182 starterProject.SubDir)
183 if err != nil {
184 return err
185 }
186 }
187 if verbose {
188 downloadSpinner.End(true)
189 }
190
191 return nil
192
193 }
194
View as plain text