<commit_before>package empire

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"regexp"
	"strings"
	"time"

	"gopkg.in/gorp.v1"
)

var ErrInvalidName = errors.New("An app name must alphanumeric and dashes only, 3-30 chars in length.")

var NamePattern = regexp.MustCompile(`^[a-z][a-z0-9-]{2,30}$`)

// AppName represents the unique name for an App.
type AppName string

// Scan implements the sql.Scanner interface.
func (n *AppName) Scan(src interface{}) error {
	if src, ok := src.([]byte); ok {
		*n = AppName(src)
	}

	return nil
}

// Value implements the driver.Value interface.
func (n AppName) Value() (driver.Value, error) {
	return driver.Value(string(n)), nil
}

// NewNameFromRepo generates a new name from a Repo
//
//	remind101/r101-api => r101-api
func NewAppNameFromRepo(repo Repo) AppName {
	p := strings.Split(string(repo), "/")
	return AppName(p[len(p)-1])
}

// App represents an app.
type App struct {
	Name AppName `json:"name" db:"name"`

	// The associated Docker repo.
	Repo Repo `json:"repo" db:"repo"`

	CreatedAt time.Time `json:"created_at" db:"created_at"`
}

// NewApp validates the name of the new App then returns a new App instance. If the
// name is invalid, an error is retuend.
func NewApp(name AppName, repo Repo) (*App, error) {
	if !NamePattern.Match([]byte(name)) {
		return nil, ErrInvalidName
	}

	return &App{
		Name: name,
		Repo: repo,
	}, nil
}

// NewAppFromRepo returns a new App initialized from the name of a Repo.
func NewAppFromRepo(repo Repo) (*App, error) {
	name := NewAppNameFromRepo(repo)
	return NewApp(name, repo)
}

// PreInsert implements a pre insert hook for the db interface
func (a *App) PreInsert(s gorp.SqlExecutor) error {
	a.CreatedAt = Now()
	return nil
}

type AppsCreator interface {
	AppsCreate(*App) (*App, error)
}

type AppsDestroyer interface {
	AppsDestroy(*App) error
}

type AppsFinder interface {
	AppsAll() ([]*App, error)
	AppsFind(AppName) (*App, error)
	AppsFindByRepo(Repo) (*App, error)
	AppsFindOrCreateByRepo(Repo) (*App, error)
}

type AppsService interface {
	AppsCreator
	AppsDestroyer
	AppsFinder
}

type appsService struct {
	DB
	JobsService
}

func (s *appsService) AppsCreate(app *App) (*App, error) {
	return AppsCreate(s.DB, app)
}

func (s *appsService) AppsDestroy(app *App) error {
	if err := AppsDestroy(s.DB, app); err != nil {
		return err
	}

	jobs, err := s.JobsList(JobsListQuery{App: app.Name})
	if err != nil {
		return err
	}

	if err := s.Unschedule(jobs...); err != nil {
		return err
	}

	return nil
}
<commit_msg>Simpler<commit_after>package empire

import (
	"database/sql"
	"database/sql/driver"
	"errors"
	"regexp"
	"strings"
	"time"

	"gopkg.in/gorp.v1"
)

var ErrInvalidName = errors.New("An app name must alphanumeric and dashes only, 3-30 chars in length.")

var NamePattern = regexp.MustCompile(`^[a-z][a-z0-9-]{2,30}$`)

// AppName represents the unique name for an App.
type AppName string

// Scan implements the sql.Scanner interface.
func (n *AppName) Scan(src interface{}) error {
	if src, ok := src.([]byte); ok {
		*n = AppName(src)
	}

	return nil
}

// Value implements the driver.Value interface.
func (n AppName) Value() (driver.Value, error) {
	return driver.Value(string(n)), nil
}

// NewNameFromRepo generates a new name from a Repo
//
//	remind101/r101-api => r101-api
func NewAppNameFromRepo(repo Repo) AppName {
	p := strings.Split(string(repo), "/")
	return AppName(p[len(p)-1])
}

// App represents an app.
type App struct {
	Name AppName `json:"name" db:"name"`

	// The associated Docker repo.
	Repo Repo `json:"repo" db:"repo"`

	CreatedAt time.Time `json:"created_at" db:"created_at"`
}

// NewApp validates the name of the new App then returns a new App instance. If the
// name is invalid, an error is retuend.
func NewApp(name AppName, repo Repo) (*App, error) {
	if !NamePattern.Match([]byte(name)) {
		return nil, ErrInvalidName
	}

	return &App{
		Name: name,
		Repo: repo,
	}, nil
}

// NewAppFromRepo returns a new App initialized from the name of a Repo.
func NewAppFromRepo(repo Repo) (*App, error) {
	name := NewAppNameFromRepo(repo)
	return NewApp(name, repo)
}

// PreInsert implements a pre insert hook for the db interface
func (a *App) PreInsert(s gorp.SqlExecutor) error {
	a.CreatedAt = Now()
	return nil
}

type AppsCreator interface {
	AppsCreate(*App) (*App, error)
}

type AppsDestroyer interface {
	AppsDestroy(*App) error
}

type AppsFinder interface {
	AppsAll() ([]*App, error)
	AppsFind(AppName) (*App, error)
	AppsFindByRepo(Repo) (*App, error)
	AppsFindOrCreateByRepo(Repo) (*App, error)
}

type AppsService interface {
	AppsCreator
	AppsDestroyer
	AppsFinder
}

type appsService struct {
	DB
	JobsService
}

func (s *appsService) AppsCreate(app *App) (*App, error) {
	return AppsCreate(s.DB, app)
}

func (s *appsService) AppsDestroy(app *App) error {
	if err := AppsDestroy(s.DB, app); err != nil {
		return err
	}

	jobs, err := s.JobsList(JobsListQuery{App: app.Name})
	if err != nil {
		return err
	}

	return s.Unschedule(jobs...)
}

{'fraction_non_alphanumeric': 0.1358392999204455, 'fraction_numerical': 0.007557677008750994, 'mean_word_length': 4.126401630988787, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1918276', 'n_tokens_mistral': 1880, 'n_tokens_neox': 1827, 'n_words': 545}