manifest.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. package server
  2. import (
  3. "bytes"
  4. "crypto/sha256"
  5. "encoding/json"
  6. "fmt"
  7. "io"
  8. "os"
  9. "path/filepath"
  10. "github.com/ollama/ollama/types/model"
  11. )
  12. type Manifest struct {
  13. ManifestV2
  14. filepath string
  15. digest string
  16. }
  17. func (m *Manifest) Size() (size int64) {
  18. for _, layer := range append(m.Layers, m.Config) {
  19. size += layer.Size
  20. }
  21. return
  22. }
  23. func (m *Manifest) Remove() error {
  24. if err := os.Remove(m.filepath); err != nil {
  25. return err
  26. }
  27. for _, layer := range append(m.Layers, m.Config) {
  28. if err := layer.Remove(); err != nil {
  29. return err
  30. }
  31. }
  32. manifests, err := GetManifestPath()
  33. if err != nil {
  34. return err
  35. }
  36. return PruneDirectory(manifests)
  37. }
  38. func ParseNamedManifest(n model.Name) (*Manifest, error) {
  39. if !n.IsFullyQualified() {
  40. return nil, model.Unqualified(n)
  41. }
  42. manifests, err := GetManifestPath()
  43. if err != nil {
  44. return nil, err
  45. }
  46. p := filepath.Join(manifests, n.Filepath())
  47. var m ManifestV2
  48. f, err := os.Open(p)
  49. if err != nil {
  50. return nil, err
  51. }
  52. defer f.Close()
  53. sha256sum := sha256.New()
  54. if err := json.NewDecoder(io.TeeReader(f, sha256sum)).Decode(&m); err != nil {
  55. return nil, err
  56. }
  57. return &Manifest{
  58. ManifestV2: m,
  59. filepath: p,
  60. digest: fmt.Sprintf("%x", sha256sum.Sum(nil)),
  61. }, nil
  62. }
  63. func WriteManifest(name string, config *Layer, layers []*Layer) error {
  64. manifest := ManifestV2{
  65. SchemaVersion: 2,
  66. MediaType: "application/vnd.docker.distribution.manifest.v2+json",
  67. Config: config,
  68. Layers: layers,
  69. }
  70. var b bytes.Buffer
  71. if err := json.NewEncoder(&b).Encode(manifest); err != nil {
  72. return err
  73. }
  74. modelpath := ParseModelPath(name)
  75. manifestPath, err := modelpath.GetManifestPath()
  76. if err != nil {
  77. return err
  78. }
  79. if err := os.MkdirAll(filepath.Dir(manifestPath), 0o755); err != nil {
  80. return err
  81. }
  82. return os.WriteFile(manifestPath, b.Bytes(), 0o644)
  83. }
  84. func Manifests() (map[model.Name]*Manifest, error) {
  85. manifests, err := GetManifestPath()
  86. if err != nil {
  87. return nil, err
  88. }
  89. // TODO(mxyng): use something less brittle
  90. matches, err := filepath.Glob(fmt.Sprintf("%s/*/*/*/*", manifests))
  91. if err != nil {
  92. return nil, err
  93. }
  94. ms := make(map[model.Name]*Manifest)
  95. for _, match := range matches {
  96. rel, err := filepath.Rel(manifests, match)
  97. if err != nil {
  98. return nil, err
  99. }
  100. n := model.ParseNameFromFilepath(rel)
  101. if n.IsValid() {
  102. m, err := ParseNamedManifest(n)
  103. if err != nil {
  104. return nil, err
  105. }
  106. ms[n] = m
  107. }
  108. }
  109. return ms, nil
  110. }