knotserver: add helpers to read and parse .gitmodules files #788

merged
opened by oppi.li targeting master from push-lqyxyyrozyxs
Changed files
+60 -2
knotserver
git
+60 -2
knotserver/git/git.go
··· 3 import ( 4 "archive/tar" 5 "bytes" 6 "fmt" 7 "io" 8 "io/fs" ··· 12 "time" 13 14 "github.com/go-git/go-git/v5" 15 "github.com/go-git/go-git/v5/plumbing" 16 "github.com/go-git/go-git/v5/plumbing/object" 17 ) 18 19 var ( 20 - ErrBinaryFile = fmt.Errorf("binary file") 21 - ErrNotBinaryFile = fmt.Errorf("not binary file") 22 ) 23 24 type GitRepo struct { ··· 190 return io.ReadAll(reader) 191 } 192 193 func (g *GitRepo) Branch(name string) (*plumbing.Reference, error) { 194 ref, err := g.r.Reference(plumbing.NewBranchReferenceName(name), false) 195 if err != nil {
··· 3 import ( 4 "archive/tar" 5 "bytes" 6 + "errors" 7 "fmt" 8 "io" 9 "io/fs" ··· 13 "time" 14 15 "github.com/go-git/go-git/v5" 16 + "github.com/go-git/go-git/v5/config" 17 "github.com/go-git/go-git/v5/plumbing" 18 "github.com/go-git/go-git/v5/plumbing/object" 19 ) 20 21 var ( 22 + ErrBinaryFile = errors.New("binary file") 23 + ErrNotBinaryFile = errors.New("not binary file") 24 + ErrMissingGitModules = errors.New("no .gitmodules file found") 25 + ErrInvalidGitModules = errors.New("invalid .gitmodules file") 26 + ErrNotSubmodule = errors.New("path is not a submodule") 27 ) 28 29 type GitRepo struct { ··· 195 return io.ReadAll(reader) 196 } 197 198 + // read and parse .gitmodules 199 + func (g *GitRepo) Submodules() (*config.Modules, error) { 200 + c, err := g.r.CommitObject(g.h) 201 + if err != nil { 202 + return nil, fmt.Errorf("commit object: %w", err) 203 + } 204 + 205 + tree, err := c.Tree() 206 + if err != nil { 207 + return nil, fmt.Errorf("tree: %w", err) 208 + } 209 + 210 + // read .gitmodules file 211 + modulesEntry, err := tree.FindEntry(".gitmodules") 212 + if err != nil { 213 + return nil, fmt.Errorf("%w: %w", ErrMissingGitModules, err) 214 + } 215 + 216 + modulesFile, err := tree.TreeEntryFile(modulesEntry) 217 + if err != nil { 218 + return nil, fmt.Errorf("%w: failed to read file: %w", ErrInvalidGitModules, err) 219 + } 220 + 221 + content, err := modulesFile.Contents() 222 + if err != nil { 223 + return nil, fmt.Errorf("%w: failed to read contents: %w", ErrInvalidGitModules, err) 224 + } 225 + 226 + // parse .gitmodules 227 + modules := config.NewModules() 228 + if err = modules.Unmarshal([]byte(content)); err != nil { 229 + return nil, fmt.Errorf("%w: failed to parse: %w", ErrInvalidGitModules, err) 230 + } 231 + 232 + return modules, nil 233 + } 234 + 235 + func (g *GitRepo) Submodule(path string) (*config.Submodule, error) { 236 + modules, err := g.Submodules() 237 + if err != nil { 238 + return nil, err 239 + } 240 + 241 + for _, submodule := range modules.Submodules { 242 + if submodule.Path == path { 243 + return submodule, nil 244 + } 245 + } 246 + 247 + // path is not a submodule 248 + return nil, ErrNotSubmodule 249 + } 250 + 251 func (g *GitRepo) Branch(name string) (*plumbing.Reference, error) { 252 ref, err := g.r.Reference(plumbing.NewBranchReferenceName(name), false) 253 if err != nil {