mirror of https://github.com/ollama/ollama.git
				
				
				
			
		
			
				
	
	
		
			162 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			Go
		
	
	
	
| package server
 | |
| 
 | |
| import (
 | |
| 	"crypto/sha256"
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"log/slog"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 
 | |
| 	"github.com/ollama/ollama/types/model"
 | |
| )
 | |
| 
 | |
| type Manifest struct {
 | |
| 	ManifestV2
 | |
| 
 | |
| 	filepath string
 | |
| 	fi       os.FileInfo
 | |
| 	digest   string
 | |
| }
 | |
| 
 | |
| func (m *Manifest) Size() (size int64) {
 | |
| 	for _, layer := range append(m.Layers, m.Config) {
 | |
| 		size += layer.Size
 | |
| 	}
 | |
| 
 | |
| 	return
 | |
| }
 | |
| 
 | |
| func (m *Manifest) Remove() error {
 | |
| 	if err := os.Remove(m.filepath); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	manifests, err := GetManifestPath()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return PruneDirectory(manifests)
 | |
| }
 | |
| 
 | |
| func (m *Manifest) RemoveLayers() error {
 | |
| 	for _, layer := range append(m.Layers, m.Config) {
 | |
| 		if err := layer.Remove(); err != nil {
 | |
| 			return err
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func ParseNamedManifest(n model.Name) (*Manifest, error) {
 | |
| 	if !n.IsFullyQualified() {
 | |
| 		return nil, model.Unqualified(n)
 | |
| 	}
 | |
| 
 | |
| 	manifests, err := GetManifestPath()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	p := filepath.Join(manifests, n.Filepath())
 | |
| 
 | |
| 	var m ManifestV2
 | |
| 	f, err := os.Open(p)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	fi, err := f.Stat()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	sha256sum := sha256.New()
 | |
| 	if err := json.NewDecoder(io.TeeReader(f, sha256sum)).Decode(&m); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	return &Manifest{
 | |
| 		ManifestV2: m,
 | |
| 		filepath:   p,
 | |
| 		fi:         fi,
 | |
| 		digest:     fmt.Sprintf("%x", sha256sum.Sum(nil)),
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| func WriteManifest(name model.Name, config *Layer, layers []*Layer) error {
 | |
| 	manifests, err := GetManifestPath()
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	p := filepath.Join(manifests, name.Filepath())
 | |
| 	if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	f, err := os.Create(p)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 
 | |
| 	m := ManifestV2{
 | |
| 		SchemaVersion: 2,
 | |
| 		MediaType:     "application/vnd.docker.distribution.manifest.v2+json",
 | |
| 		Config:        config,
 | |
| 		Layers:        layers,
 | |
| 	}
 | |
| 
 | |
| 	return json.NewEncoder(f).Encode(m)
 | |
| }
 | |
| 
 | |
| func Manifests() (map[model.Name]*Manifest, error) {
 | |
| 	manifests, err := GetManifestPath()
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	// TODO(mxyng): use something less brittle
 | |
| 	matches, err := filepath.Glob(filepath.Join(manifests, "*", "*", "*", "*"))
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	ms := make(map[model.Name]*Manifest)
 | |
| 	for _, match := range matches {
 | |
| 		fi, err := os.Stat(match)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		if !fi.IsDir() {
 | |
| 			rel, err := filepath.Rel(manifests, match)
 | |
| 			if err != nil {
 | |
| 				slog.Warn("bad filepath", "path", match, "error", err)
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			n := model.ParseNameFromFilepath(rel)
 | |
| 			if !n.IsValid() {
 | |
| 				slog.Warn("bad manifest name", "path", rel, "error", err)
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			m, err := ParseNamedManifest(n)
 | |
| 			if err != nil {
 | |
| 				slog.Warn("bad manifest", "name", n, "error", err)
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			ms[n] = m
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return ms, nil
 | |
| }
 |