github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/test/scripts/cmd/dependencies/github.go (about) 1 package dependencies 2 3 import ( 4 "os" 5 "path/filepath" 6 7 "github.com/0xPolygon/supernets2-node/log" 8 "github.com/go-git/go-billy/v5" 9 "github.com/go-git/go-billy/v5/helper/chroot" 10 "github.com/go-git/go-git/v5" 11 "github.com/go-git/go-git/v5/plumbing/transport" 12 "github.com/go-git/go-git/v5/plumbing/transport/http" 13 "github.com/go-git/go-git/v5/plumbing/transport/ssh" 14 "github.com/go-git/go-git/v5/storage/memory" 15 "github.com/spf13/afero" 16 ) 17 18 type githubManager struct { 19 aferoFs afero.Fs 20 21 sshKey string 22 token string 23 } 24 25 func newGithubManager(aferoFs afero.Fs, sshKey, token string) *githubManager { 26 return &githubManager{ 27 aferoFs: aferoFs, 28 token: token, 29 sshKey: sshKey, 30 } 31 } 32 33 func (gm *githubManager) cloneTargetRepo(repoURL string) (string, error) { 34 tmpdir, err := afero.TempDir(gm.aferoFs, "", "supernets2-node-deps") 35 if err != nil { 36 return "", err 37 } 38 billyFS := newAdapter(gm.aferoFs) 39 billyFS, err = billyFS.Chroot(tmpdir) 40 if err != nil { 41 return "", err 42 } 43 cloneOptions := &git.CloneOptions{ 44 URL: repoURL, 45 } 46 if gm.token != "" || gm.sshKey != "" { 47 auth, err := gm.determineAuth() 48 if err != nil { 49 return "", err 50 } 51 if auth != nil { 52 cloneOptions.Auth = auth 53 } 54 } 55 storer := memory.NewStorage() 56 _, err = git.Clone(storer, billyFS, cloneOptions) 57 if err != nil { 58 return "", err 59 } 60 return tmpdir, nil 61 } 62 63 func (gm *githubManager) determineAuth() (transport.AuthMethod, error) { 64 if gm.token != "" { 65 return &http.BasicAuth{ 66 Username: "int-bot", // this can be anything except an empty string 67 Password: gm.token, 68 }, nil 69 } 70 71 pvkFile, err := afero.TempFile(gm.aferoFs, "", "") 72 if err != nil { 73 return nil, err 74 } 75 defer func() { 76 if err := gm.aferoFs.Remove(pvkFile.Name()); err != nil { 77 log.Errorf("Could not remove temporary file %q: %v", pvkFile.Name(), err) 78 } 79 }() 80 _, err = pvkFile.WriteString(gm.sshKey + "\n") 81 if err != nil { 82 return nil, err 83 } 84 const defaultUser = "git" 85 auth, err := ssh.NewPublicKeysFromFile(defaultUser, pvkFile.Name(), "") 86 if err != nil { 87 return nil, err 88 } 89 90 return auth, nil 91 } 92 93 const ( 94 defaultDirectoryMode = 0755 95 defaultCreateMode = 0666 96 ) 97 98 // AdapterFs holds an afero Fs interface for adaptation to billy.Filesystem. 99 type AdapterFs struct { 100 fs afero.Fs 101 } 102 103 func newAdapter(fs afero.Fs) billy.Filesystem { 104 return chroot.New(&AdapterFs{fs}, "/") 105 } 106 107 // Create creates a new file. 108 func (fs *AdapterFs) Create(filename string) (billy.File, error) { 109 return fs.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, defaultCreateMode) 110 } 111 112 // OpenFile opens a file. 113 func (fs *AdapterFs) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) { 114 if flag&os.O_CREATE != 0 { 115 if err := fs.createDir(filename); err != nil { 116 return nil, err 117 } 118 } 119 120 f, err := fs.fs.OpenFile(filename, flag, perm) 121 if err != nil { 122 return nil, err 123 } 124 125 mutexFile := &file{ 126 File: f, 127 } 128 129 return mutexFile, err 130 } 131 132 func (fs *AdapterFs) createDir(fullpath string) error { 133 dir := filepath.Dir(fullpath) 134 if dir != "." { 135 if err := fs.fs.MkdirAll(dir, defaultDirectoryMode); err != nil { 136 return err 137 } 138 } 139 140 return nil 141 } 142 143 // ReadDir reads a directory. 144 func (fs *AdapterFs) ReadDir(path string) ([]os.FileInfo, error) { 145 l, err := afero.ReadDir(fs.fs, path) 146 if err != nil { 147 return nil, err 148 } 149 150 var s = make([]os.FileInfo, len(l)) 151 copy(s, l) 152 153 return s, nil 154 } 155 156 // Rename renames the given file. 157 func (fs *AdapterFs) Rename(from, to string) error { 158 if err := fs.createDir(to); err != nil { 159 return err 160 } 161 162 return os.Rename(from, to) 163 } 164 165 // MkdirAll creates directories recursively. 166 func (fs *AdapterFs) MkdirAll(path string, perm os.FileMode) error { 167 return fs.fs.MkdirAll(path, defaultDirectoryMode) 168 } 169 170 // Open opens a file. 171 func (fs *AdapterFs) Open(filename string) (billy.File, error) { 172 return fs.OpenFile(filename, os.O_RDONLY, 0) 173 } 174 175 // Stat returns information about a file. 176 func (fs *AdapterFs) Stat(filename string) (os.FileInfo, error) { 177 return fs.fs.Stat(filename) 178 } 179 180 // Remove deletes a file. 181 func (fs *AdapterFs) Remove(filename string) error { 182 return fs.fs.Remove(filename) 183 } 184 185 // TempFile creates a temporary file. 186 func (fs *AdapterFs) TempFile(dir, prefix string) (billy.File, error) { 187 if err := fs.createDir(dir + string(os.PathSeparator)); err != nil { 188 return nil, err 189 } 190 191 f, err := afero.TempFile(fs.fs, dir, prefix) 192 if err != nil { 193 return nil, err 194 } 195 return &file{File: f}, nil 196 } 197 198 // Join returns a string with joined paths. 199 func (fs *AdapterFs) Join(elem ...string) string { 200 return filepath.Join(elem...) 201 } 202 203 // RemoveAll removes directories recursively. 204 func (fs *AdapterFs) RemoveAll(path string) error { 205 return fs.fs.RemoveAll(filepath.Clean(path)) 206 } 207 208 // Lstat returns information about a file. 209 func (fs *AdapterFs) Lstat(filename string) (os.FileInfo, error) { 210 info, success := fs.fs.(afero.Lstater) 211 if success { 212 s, _, err := info.LstatIfPossible(filename) 213 if err != nil { 214 return nil, err 215 } 216 217 return s, nil 218 } 219 220 return fs.fs.Stat(filename) 221 } 222 223 // Symlink creates a symbolic link. 224 func (fs *AdapterFs) Symlink(target, link string) error { 225 if err := fs.createDir(link); err != nil { 226 return err 227 } 228 229 // TODO afero does not support symlinks 230 return nil 231 } 232 233 // Readlink is not currently implemented. 234 func (fs *AdapterFs) Readlink(link string) (string, error) { 235 // TODO afero does not support symlinks 236 return "", nil 237 } 238 239 // Capabilities implements the Capable interface. 240 func (fs *AdapterFs) Capabilities() billy.Capability { 241 return billy.DefaultCapabilities 242 } 243 244 // file is a wrapper for an os.File which adds support for file locking. 245 type file struct { 246 afero.File 247 } 248 249 // Lock is not currently implemented. 250 func (f *file) Lock() error { 251 return nil 252 } 253 254 // Unlock is not currently implemented. 255 func (f *file) Unlock() error { 256 return nil 257 }