@@ -10,6 +10,7 @@ import (
1010 "os"
1111 "path"
1212 "path/filepath"
13+ "time"
1314
1415 "github.com/pluralsh/plural-cli/pkg/utils/pathing"
1516 "sigs.k8s.io/yaml"
@@ -66,20 +67,6 @@ func EmptyDirectory(dir string) error {
6667 return nil
6768}
6869
69- func IsEmpty (name string ) (bool , error ) {
70- f , err := os .Open (name )
71- if err != nil {
72- return false , err
73- }
74- defer f .Close ()
75-
76- _ , err = f .Readdirnames (1 ) // Or f.Readdir(1)
77- if errors .Is (err , io .EOF ) {
78- return true , nil
79- }
80- return false , err // Either not empty or error, suits both cases
81- }
82-
8370func WriteFile (name string , content []byte ) error {
8471 if err := os .MkdirAll (filepath .Dir (name ), 0755 ); err != nil {
8572 return err
@@ -106,6 +93,52 @@ func ReadRemoteFile(url string) (string, error) {
10693 return buffer .String (), nil
10794}
10895
96+ func ReadRemoteFileWithRetries (url , token string , retries int ) (io.ReadCloser , error ) {
97+ req , err := http .NewRequest (http .MethodGet , url , nil )
98+ if err != nil {
99+ return nil , err
100+ }
101+ req .Header .Add ("Authorization" , "Token " + token )
102+
103+ for i := 0 ; i < retries ; i ++ {
104+ resp , retriable , err := doRequest (req )
105+ if err != nil {
106+ if ! retriable {
107+ return nil , err
108+ }
109+
110+ time .Sleep (time .Duration (50 * (i + 1 )) * time .Millisecond )
111+ continue
112+ }
113+
114+ return resp , nil
115+ }
116+
117+ return nil , fmt .Errorf ("could read file, retries exhaused: %w" , err )
118+ }
119+
120+ func doRequest (req * http.Request ) (io.ReadCloser , bool , error ) {
121+ client := & http.Client {Timeout : time .Minute , Transport : & http.Transport {ResponseHeaderTimeout : time .Minute }}
122+
123+ resp , err := client .Do (req )
124+ if err != nil {
125+ return nil , false , err
126+ }
127+
128+ if resp .StatusCode != http .StatusOK {
129+ defer resp .Body .Close ()
130+ errMsg , err := io .ReadAll (resp .Body )
131+ if err != nil {
132+ return nil , false , fmt .Errorf ("could not read response body: %w" , err )
133+ }
134+
135+ return nil , resp .StatusCode == http .StatusTooManyRequests ,
136+ fmt .Errorf ("could not fetch url: %s, error: %s, code: %d" , req .URL .String (), string (errMsg ), resp .StatusCode )
137+ }
138+
139+ return resp .Body , false , nil
140+ }
141+
109142func YamlFile (name string , out interface {}) error {
110143 content , err := os .ReadFile (name )
111144 if err != nil {
@@ -195,3 +228,50 @@ func CopyDir(src string, dst string) error {
195228 }
196229 return nil
197230}
231+
232+ func EnsureDir (dir string ) error {
233+ if dir == "" {
234+ return fmt .Errorf ("directory name cannot be empty" )
235+ }
236+
237+ if ! Exists (dir ) {
238+ return os .MkdirAll (dir , 0755 )
239+ }
240+
241+ if ! IsDir (dir ) {
242+ return fmt .Errorf ("%s is not a directory" , dir )
243+ }
244+
245+ return nil
246+ }
247+
248+ func EnsureEmptyDir (dir string ) error {
249+ if err := EnsureDir (dir ); err != nil {
250+ return err
251+ }
252+
253+ empty , err := IsEmptyDir (dir )
254+ if err != nil {
255+ return fmt .Errorf ("could not check if directory %s is empty: %w" , dir , err )
256+ }
257+
258+ if ! empty {
259+ return fmt .Errorf ("directory %s is not empty" , dir )
260+ }
261+
262+ return nil
263+ }
264+
265+ func IsEmptyDir (name string ) (bool , error ) {
266+ f , err := os .Open (name )
267+ if err != nil {
268+ return false , err
269+ }
270+ defer f .Close ()
271+
272+ _ , err = f .Readdirnames (1 ) // Or f.Readdir(1)
273+ if errors .Is (err , io .EOF ) {
274+ return true , nil
275+ }
276+ return false , err // Either not empty or error, suits both cases
277+ }
0 commit comments