All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 32s
				
			Test / Sandbox (push) Successful in 2m29s
				
			Test / Hakurei (push) Successful in 4m6s
				
			Test / Hpkg (push) Successful in 4m45s
				
			Test / Sandbox (race detector) (push) Successful in 4m48s
				
			Test / Hakurei (race detector) (push) Successful in 6m4s
				
			Test / Flake checks (push) Successful in 1m26s
				
			This was a stopgap solution that lasted for way too long. This finally removes it and prepares internal/app for some major changes. Signed-off-by: Ophestra <cat@gensokyo.uk>
		
			
				
	
	
		
			86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package app implements high-level hakurei container behaviour.
 | |
| package app
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"log"
 | |
| 	"sync"
 | |
| 
 | |
| 	"hakurei.app/hst"
 | |
| 	"hakurei.app/internal/app/state"
 | |
| 	"hakurei.app/internal/sys"
 | |
| )
 | |
| 
 | |
| // New returns the address of a newly initialised [App] struct.
 | |
| func New(ctx context.Context, os sys.State) (*App, error) {
 | |
| 	a := new(App)
 | |
| 	a.sys = os
 | |
| 	a.ctx = ctx
 | |
| 
 | |
| 	id := new(state.ID)
 | |
| 	err := state.NewAppID(id)
 | |
| 	a.id = newID(id)
 | |
| 
 | |
| 	return a, err
 | |
| }
 | |
| 
 | |
| // MustNew calls [New] and panics if an error is returned.
 | |
| func MustNew(ctx context.Context, os sys.State) *App {
 | |
| 	a, err := New(ctx, os)
 | |
| 	if err != nil {
 | |
| 		log.Fatalf("cannot create app: %v", err)
 | |
| 	}
 | |
| 	return a
 | |
| }
 | |
| 
 | |
| // An App keeps track of the hakurei container lifecycle.
 | |
| type App struct {
 | |
| 	outcome *Outcome
 | |
| 
 | |
| 	id  *stringPair[state.ID]
 | |
| 	sys sys.State
 | |
| 	ctx context.Context
 | |
| 	mu  sync.RWMutex
 | |
| }
 | |
| 
 | |
| // ID returns a copy of [state.ID] held by App.
 | |
| func (a *App) ID() state.ID { a.mu.RLock(); defer a.mu.RUnlock(); return a.id.unwrap() }
 | |
| 
 | |
| func (a *App) String() string {
 | |
| 	if a == nil {
 | |
| 		return "<nil>"
 | |
| 	}
 | |
| 
 | |
| 	a.mu.RLock()
 | |
| 	defer a.mu.RUnlock()
 | |
| 
 | |
| 	if a.outcome != nil {
 | |
| 		if a.outcome.user.uid == nil {
 | |
| 			return "<invalid>"
 | |
| 		}
 | |
| 		return fmt.Sprintf("sealed app %s as uid %s", a.id, a.outcome.user.uid)
 | |
| 	}
 | |
| 
 | |
| 	return fmt.Sprintf("unsealed app %s", a.id)
 | |
| }
 | |
| 
 | |
| // Seal determines the [Outcome] of [hst.Config].
 | |
| // Values stored in and referred to by [hst.Config] might be overwritten and must not be used again.
 | |
| func (a *App) Seal(config *hst.Config) (*Outcome, error) {
 | |
| 	a.mu.Lock()
 | |
| 	defer a.mu.Unlock()
 | |
| 
 | |
| 	if a.outcome != nil {
 | |
| 		panic("attempting to seal app twice")
 | |
| 	}
 | |
| 
 | |
| 	seal := new(Outcome)
 | |
| 	seal.id = a.id
 | |
| 	err := seal.finalise(a.ctx, a.sys, config)
 | |
| 	if err == nil {
 | |
| 		a.outcome = seal
 | |
| 	}
 | |
| 	return seal, err
 | |
| }
 |