x/build: fix some build errors
This commit is contained in:
parent
6917865bf3
commit
42cda9dd46
@ -8,7 +8,6 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"bllamo.com/build/blob"
|
|
||||||
"bllamo.com/build/internal/blobstore"
|
"bllamo.com/build/internal/blobstore"
|
||||||
"bllamo.com/model"
|
"bllamo.com/model"
|
||||||
)
|
)
|
||||||
@ -53,8 +52,8 @@ func Open(dir string) (*Server, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) Build(ref string, f model.File) error {
|
func (s *Server) Build(ref string, f model.File) error {
|
||||||
br := blob.ParseRef(ref)
|
mp := model.ParsePath(ref)
|
||||||
if !br.CompleteWithoutBuild() {
|
if !mp.CompleteWithoutBuild() {
|
||||||
return fmt.Errorf("%w: %q", ErrIncompleteRef, ref)
|
return fmt.Errorf("%w: %q", ErrIncompleteRef, ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ func (s *Server) Build(ref string, f model.File) error {
|
|||||||
// 5. Done.
|
// 5. Done.
|
||||||
|
|
||||||
if f.From == "" {
|
if f.From == "" {
|
||||||
return &model.Error{Pragma: "FROM", Message: "missing"}
|
return &model.FileError{Pragma: "FROM", Message: "missing"}
|
||||||
}
|
}
|
||||||
|
|
||||||
var layers []layerJSON
|
var layers []layerJSON
|
||||||
@ -98,7 +97,7 @@ func (s *Server) Build(ref string, f model.File) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return s.setManifestData(
|
return s.setManifestData(
|
||||||
br.WithBuild(info.FileType.String()),
|
mp.WithBuild(info.FileType.String()),
|
||||||
data,
|
data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -113,13 +112,13 @@ func (s *Server) LayerFile(digest string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ManifestData(ref string) ([]byte, error) {
|
func (s *Server) ManifestData(ref string) ([]byte, error) {
|
||||||
data, _, err := s.resolve(blob.ParseRef(ref))
|
data, _, err := s.resolve(model.ParsePath(ref))
|
||||||
return data, err
|
return data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// WeightFile returns the absolute path to the weights file for the given model ref.
|
// WeightFile returns the absolute path to the weights file for the given model ref.
|
||||||
func (s *Server) WeightsFile(ref string) (string, error) {
|
func (s *Server) WeightsFile(ref string) (string, error) {
|
||||||
m, err := s.getManifest(blob.ParseRef(ref))
|
m, err := s.getManifest(model.ParsePath(ref))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -140,12 +139,12 @@ func (s *Server) WeightsFile(ref string) (string, error) {
|
|||||||
// blob, and then have the ref point to that blob. This would simplify the
|
// blob, and then have the ref point to that blob. This would simplify the
|
||||||
// code, allow us to have integrity checks on the manifest, and clean up
|
// code, allow us to have integrity checks on the manifest, and clean up
|
||||||
// this interface.
|
// this interface.
|
||||||
func (s *Server) resolve(ref blob.Ref) (data []byte, path string, err error) {
|
func (s *Server) resolve(ref model.Path) (data []byte, fileName string, err error) {
|
||||||
path, err = s.refFileName(ref)
|
fileName, err = s.refFileName(ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
data, err = os.ReadFile(path)
|
data, err = os.ReadFile(fileName)
|
||||||
if errors.Is(err, fs.ErrNotExist) {
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
return nil, "", fmt.Errorf("%w: %q", ErrNotFound, ref)
|
return nil, "", fmt.Errorf("%w: %q", ErrNotFound, ref)
|
||||||
}
|
}
|
||||||
@ -155,16 +154,16 @@ func (s *Server) resolve(ref blob.Ref) (data []byte, path string, err error) {
|
|||||||
// be on disk later.
|
// be on disk later.
|
||||||
return nil, "", fmt.Errorf("manifest read error: %v", err)
|
return nil, "", fmt.Errorf("manifest read error: %v", err)
|
||||||
}
|
}
|
||||||
return data, path, nil
|
return data, fileName, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) SetManifestData(ref string, data []byte) error {
|
func (s *Server) SetManifestData(ref string, data []byte) error {
|
||||||
return s.setManifestData(blob.ParseRef(ref), data)
|
return s.setManifestData(model.ParsePath(ref), data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sets the data for the given ref.
|
// Set sets the data for the given ref.
|
||||||
func (s *Server) setManifestData(br blob.Ref, data []byte) error {
|
func (s *Server) setManifestData(mp model.Path, data []byte) error {
|
||||||
path, err := s.refFileName(br)
|
path, err := s.refFileName(mp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -177,11 +176,11 @@ func (s *Server) setManifestData(br blob.Ref, data []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) refFileName(ref blob.Ref) (string, error) {
|
func (s *Server) refFileName(mp model.Path) (string, error) {
|
||||||
if !ref.Complete() {
|
if !mp.Complete() {
|
||||||
return "", fmt.Errorf("ref not fully qualified: %q", ref)
|
return "", fmt.Errorf("ref not fully qualified: %q", mp)
|
||||||
}
|
}
|
||||||
return filepath.Join(s.st.Dir(), "manifests", filepath.Join(ref.Parts()...)), nil
|
return filepath.Join(s.st.Dir(), "manifests", filepath.Join(mp.Parts()...)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type manifestJSON struct {
|
type manifestJSON struct {
|
||||||
@ -197,7 +196,7 @@ type layerJSON struct {
|
|||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getManifest(ref blob.Ref) (manifestJSON, error) {
|
func (s *Server) getManifest(ref model.Path) (manifestJSON, error) {
|
||||||
data, path, err := s.resolve(ref)
|
data, path, err := s.resolve(ref)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return manifestJSON{}, err
|
return manifestJSON{}, err
|
||||||
|
@ -29,7 +29,7 @@ func TestServerBuildErrors(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("FROM pragma missing", func(t *testing.T) {
|
t.Run("FROM pragma missing", func(t *testing.T) {
|
||||||
err := s.Build(qualifiedRef, model.File{})
|
err := s.Build(qualifiedRef, model.File{})
|
||||||
var e *model.Error
|
var e *model.FileError
|
||||||
if !errors.As(err, &e) {
|
if !errors.As(err, &e) {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"bllamo.com/build/blob"
|
"bllamo.com/model"
|
||||||
"kr.dev/diff"
|
"kr.dev/diff"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -68,9 +68,9 @@ func TestStoreBasicBlob(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check tags
|
// Check tags
|
||||||
ref := blob.ParseRef("registry.ollama.ai/library/test:latest+KQED")
|
name := model.ParsePath("registry.ollama.ai/library/test:latest+KQED")
|
||||||
|
|
||||||
t.Logf("RESOLVING: %q", ref.Parts())
|
t.Logf("RESOLVING: %q", name.Parts())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,12 @@ func Merge(a, b Path) Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithBuild returns a copy of r with the build set to the given string.
|
||||||
|
func (r Path) WithBuild(build string) Path {
|
||||||
|
r.build = build
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
// Parts returns a sequence of the parts of a ref string from most specific
|
// Parts returns a sequence of the parts of a ref string from most specific
|
||||||
// to least specific.
|
// to least specific.
|
||||||
//
|
//
|
||||||
|
@ -58,19 +58,21 @@ func Serve(h HandlerFunc, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
func DecodeUserJSON[T any](field string, r io.Reader) (*T, error) {
|
func DecodeUserJSON[T any](field string, r io.Reader) (*T, error) {
|
||||||
v, err := DecodeJSON[T](r)
|
v, err := DecodeJSON[T](r)
|
||||||
if err == nil {
|
|
||||||
return v, nil
|
// Handle common JSON syntax errors
|
||||||
}
|
|
||||||
var msg string
|
|
||||||
var e *json.SyntaxError
|
var e *json.SyntaxError
|
||||||
if errors.As(err, &e) {
|
if errors.As(err, &e) {
|
||||||
msg = e.Error()
|
return nil, Invalid(field, "", e.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle type errors
|
||||||
var se *json.UnmarshalTypeError
|
var se *json.UnmarshalTypeError
|
||||||
if errors.As(err, &se) {
|
if errors.As(err, &se) {
|
||||||
msg = fmt.Sprintf("%s (%q) is not a %s", se.Field, se.Value, se.Type)
|
return nil, Invalid(field, se.Value, "expected %s", se.Type)
|
||||||
}
|
}
|
||||||
return nil, Invalid("invalid_json", field, "", msg)
|
|
||||||
|
// Return v and err as they were.
|
||||||
|
return v, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DecodeJSON[T any](r io.Reader) (*T, error) {
|
func DecodeJSON[T any](r io.Reader) (*T, error) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user