diff options
| author | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-06-09 19:35:34 +0200 | 
|---|---|---|
| committer | Gabriel A. Giovanini <mail@gabrielgio.me> | 2024-06-09 19:35:34 +0200 | 
| commit | 02614b3781f6acdfc6df0e7b07d856b2779c4ac7 (patch) | |
| tree | f23518fcf263be3236265852ba338c4fec137b41 /pkg | |
| parent | b1ad6e98445cf7dafa6fec1e2e769051fe7cb748 (diff) | |
| download | cerrado-02614b3781f6acdfc6df0e7b07d856b2779c4ac7.tar.gz cerrado-02614b3781f6acdfc6df0e7b07d856b2779c4ac7.tar.bz2 cerrado-02614b3781f6acdfc6df0e7b07d856b2779c4ac7.zip | |
feat: Per repository configuration
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/config/config.go | 134 | ||||
| -rw-r--r-- | pkg/config/config_test.go | 82 | ||||
| -rw-r--r-- | pkg/service/git.go | 19 | ||||
| -rw-r--r-- | pkg/u/list.go | 8 | ||||
| -rw-r--r-- | pkg/u/list_test.go | 30 | 
5 files changed, 235 insertions, 38 deletions
| diff --git a/pkg/config/config.go b/pkg/config/config.go index 419d49d..3e539f7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -6,6 +6,7 @@ import (  	"io"  	"os"  	"path" +	"path/filepath"  	"strconv"  	"git.gabrielgio.me/cerrado/pkg/u" @@ -13,8 +14,9 @@ import (  )  var ( -	ScanPathErr = errors.New("Scan path does not exist") -	RepoPathErr = errors.New("Repository path does not exist") +	ScanPathErr        = errors.New("Scan path does not exist") +	RepoPathErr        = errors.New("Repository path does not exist") +	InvalidPropertyErr = errors.New("Invalid property")  )  type ( @@ -26,16 +28,19 @@ type (  	}  	// configuration represents file configuration. +	// fields needs to be exported to cmp to work  	configuration struct { -		Scan       *scan -		RootReadme string +		Scan         *scan +		RootReadme   string +		Repositories []*GitRepositoryConfiguration  	}  	// This is a per repository configuration.  	GitRepositoryConfiguration struct { -		Name   string -		Path   string -		Public bool +		Name        string +		Path        string +		Description string +		Public      bool  	}  	// ConfigurationRepository represents the configuration repository (as in @@ -60,13 +65,17 @@ func LoadConfigurationRepository(configPath string) (*ConfigurationRepository, e  	}  	repo := &ConfigurationRepository{ -		rootReadme: config.RootReadme, +		rootReadme:   config.RootReadme, +		repositories: config.Repositories,  	} -	err = repo.expandOnScanPath(config.Scan.Path, config.Scan.Public) -	if err != nil { -		return nil, err +	if config.Scan.Path != "" { +		err = repo.expandOnScanPath(config.Scan.Path, config.Scan.Public) +		if err != nil { +			return nil, err +		}  	} +  	return repo, nil  } @@ -104,22 +113,32 @@ func (c *ConfigurationRepository) expandOnScanPath(scanPath string, public bool)  		return err  	} -	c.repositories = make([]*GitRepositoryConfiguration, 0)  	for _, e := range entries {  		if !e.IsDir() {  			continue  		}  		fullPath := path.Join(scanPath, e.Name()) -		c.repositories = append(c.repositories, &GitRepositoryConfiguration{ -			Name:   e.Name(), -			Path:   fullPath, -			Public: public, -		}) +		if !c.repoExits(fullPath) { +			c.repositories = append(c.repositories, &GitRepositoryConfiguration{ +				Name:   e.Name(), +				Path:   fullPath, +				Public: public, +			}) +		}  	}  	return nil  } +func (c *ConfigurationRepository) repoExits(path string) bool { +	for _, r := range c.repositories { +		if path == r.Path { +			return true +		} +	} +	return false +} +  func parse(r io.Reader) (*configuration, error) {  	block, err := scfg.Read(r)  	if err != nil { @@ -138,16 +157,82 @@ func parse(r io.Reader) (*configuration, error) {  		return nil, err  	} +	err = setRepositories(block, &config.Repositories) +	if err != nil { +		return nil, err +	} +  	return config, nil  } +func setRepositories(block scfg.Block, repositories *[]*GitRepositoryConfiguration) error { +	blocks := block.GetAll("repository") + +	for _, r := range blocks { +		if len(r.Params) != 1 { +			return fmt.Errorf( +				"Invlid number of params for repository: %w", +				InvalidPropertyErr, +			) +		} + +		path := u.FirstOrZero(r.Params) +		repository := defaultRepisotryConfiguration(path) + +		for _, d := range r.Children { +			// under repository there is only single param properties +			if len(d.Params) != 1 { +				return fmt.Errorf( +					"Invlid number of params for %s: %w", +					d.Name, +					InvalidPropertyErr, +				) +			} + +			switch d.Name { +			case "name": +				if err := setString(d, &repository.Name); err != nil { +					return err +				} +			case "description": +				if err := setString(d, &repository.Description); err != nil { +					return err +				} +			case "public": +				if err := setBool(d, &repository.Public); err != nil { +					return err +				} +			} +		} + +		*repositories = append(*repositories, repository) +	} + +	return nil +} +  func defaultConfiguration() *configuration {  	return &configuration{ -		Scan: &scan{ -			Public: true, -			Path:   "", -		}, -		RootReadme: "", +		Scan:         defaultScan(), +		RootReadme:   "", +		Repositories: make([]*GitRepositoryConfiguration, 0), +	} +} + +func defaultScan() *scan { +	return &scan{ +		Public: false, +		Path:   "", +	} + +} + +func defaultRepisotryConfiguration(path string) *GitRepositoryConfiguration { +	return &GitRepositoryConfiguration{ +		Path:        path, +		Name:        filepath.Base(path), +		Description: "", +		Public:      false,  	}  } @@ -158,6 +243,9 @@ func setRootReadme(block scfg.Block, readme *string) error {  func setScan(block scfg.Block, scan *scan) error {  	scanDir := block.Get("scan") +	if scanDir == nil { +		return nil +	}  	err := setString(scanDir, &scan.Path)  	if err != nil {  		return err @@ -182,7 +270,7 @@ func setBool(dir *scfg.Directive, field *bool) error {  func setString(dir *scfg.Directive, field *string) error {  	if dir != nil { -		*field, _ = u.First(dir.Params) +		*field = u.FirstOrZero(dir.Params)  	}  	return nil  } diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index 7afbaef..9109ecb 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -19,21 +19,94 @@ func TestFileParsing(t *testing.T) {  			config: `scan "/srv/git"`,  			expectedConfig: &configuration{  				Scan: &scan{ -					Public: true, +					Public: false,  					Path:   "/srv/git",  				}, +				Repositories: []*GitRepositoryConfiguration{},  			},  		},  		{  			name: "complete scan", -			config: `scan "/srv/git" { -	public false +			config: ` +scan "/srv/git" { +	public true  }`,  			expectedConfig: &configuration{  				Scan: &scan{ -					Public: false, +					Public: true,  					Path:   "/srv/git",  				}, +				Repositories: []*GitRepositoryConfiguration{}, +			}, +		}, +		{ +			name:   "minimal repository", +			config: `repository /srv/git/cerrado.git`, +			expectedConfig: &configuration{ +				Scan: defaultScan(), +				Repositories: []*GitRepositoryConfiguration{ +					{ +						Name:        "cerrado.git", +						Path:        "/srv/git/cerrado.git", +						Description: "", +						Public:      false, +					}, +				}, +			}, +		}, +		{ +			name: "complete repository", +			config: ` +repository /srv/git/cerrado.git { +	name cerrado +	description "Single person forge" +	public true +}`, +			expectedConfig: &configuration{ +				Scan: defaultScan(), +				Repositories: []*GitRepositoryConfiguration{ +					{ +						Name:        "cerrado", +						Path:        "/srv/git/cerrado.git", +						Description: "Single person forge", +						Public:      true, +					}, +				}, +			}, +		}, +		{ +			name: "complete", +			config: ` +scan "/srv/git" { +	public true +} + +repository /srv/git/linux.git + +repository /srv/git/cerrado.git { +	name cerrado +	description "Single person forge" +	public true +}`, +			expectedConfig: &configuration{ +				Scan: &scan{ +					Public: true, +					Path:   "/srv/git", +				}, +				Repositories: []*GitRepositoryConfiguration{ +					{ +						Name:        "linux.git", +						Path:        "/srv/git/linux.git", +						Description: "", +						Public:      false, +					}, +					{ +						Name:        "cerrado", +						Path:        "/srv/git/cerrado.git", +						Description: "Single person forge", +						Public:      true, +					}, +				},  			},  		},  	} @@ -49,7 +122,6 @@ func TestFileParsing(t *testing.T) {  			if diff := cmp.Diff(tc.expectedConfig, config); diff != "" {  				t.Errorf("Wrong result given - wanted + got\n %s", diff)  			} -  		})  	} diff --git a/pkg/service/git.go b/pkg/service/git.go index 94e2adc..7418d97 100644 --- a/pkg/service/git.go +++ b/pkg/service/git.go @@ -16,7 +16,6 @@ import (  type (  	Repository struct {  		Name           string -		Title          string  		Description    string  		LastCommitDate string  		Ref            string @@ -48,8 +47,8 @@ func NewGitService(configRepo configurationRepository) *GitService {  func (g *GitService) ListRepositories() ([]*Repository, error) {  	rs := g.configRepo.List() -	repos := make([]*Repository, len(rs)) -	for i, r := range rs { +	repos := make([]*Repository, 0, len(rs)) +	for _, r := range rs {  		repo, err := git.OpenRepository(r.Path)  		if err != nil {  			return nil, err @@ -57,12 +56,14 @@ func (g *GitService) ListRepositories() ([]*Repository, error) {  		obj, err := repo.LastCommit()  		if err != nil { -			return nil, err +			slog.Error("Error fetching last commit", "repository", r.Path, "error", err) +			continue  		}  		head, err := repo.Head()  		if err != nil { -			return nil, err +			slog.Error("Error fetching head", "repository", r.Path, "error", err) +			continue  		}  		d := path.Join(r.Path, "description") @@ -75,14 +76,12 @@ func (g *GitService) ListRepositories() ([]*Repository, error) {  			}  		} -		baseName := path.Base(r.Path) -		repos[i] = &Repository{ -			Name:           baseName, -			Title:          baseName, +		repos = append(repos, &Repository{ +			Name:           r.Name,  			Description:    description,  			LastCommitDate: obj.Author.When.Format(timeFormat),  			Ref:            head.Name().Short(), -		} +		})  	}  	return repos, nil diff --git a/pkg/u/list.go b/pkg/u/list.go index cf71909..7271ef3 100644 --- a/pkg/u/list.go +++ b/pkg/u/list.go @@ -16,6 +16,14 @@ func FirstOrZero[T any](v []T) T {  	return v[0]  } +func Map[T any, V any](ts []T, fun func(T) V) []V { +	rs := make([]V, len(ts)) +	for i := range ts { +		rs[i] = fun(ts[i]) +	} +	return rs +} +  func ChunkBy[T any](items []T, chunkSize int) [][]T {  	var chunks = make([][]T, 0, (len(items)/chunkSize)+1)  	for chunkSize < len(items) { diff --git a/pkg/u/list_test.go b/pkg/u/list_test.go index 805a209..3a856b9 100644 --- a/pkg/u/list_test.go +++ b/pkg/u/list_test.go @@ -3,6 +3,7 @@  package u  import ( +	"strconv"  	"testing"  	"github.com/google/go-cmp/cmp" @@ -129,3 +130,32 @@ func TestFirstOrZero(t *testing.T) {  		})  	}  } + +func TestMap(t *testing.T) { +	testCases := []struct { +		name string +		in   []int +		out  []string +	}{ +		{ +			name: "empty", +			in:   []int{}, +			out:  []string{}, +		}, +		{ +			name: "not empty", +			in:   []int{1, 2, 3}, +			out:  []string{"1", "2", "3"}, +		}, +	} + +	for _, tc := range testCases { +		t.Run(tc.name, func(t *testing.T) { +			out := Map(tc.in, func(v int) string { return strconv.Itoa(v) }) + +			if diff := cmp.Diff(tc.out, out); diff != "" { +				t.Errorf("Map error:\n%s", diff) +			} +		}) +	} +} | 
