manifest.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package server
  2. import (
  3. "crypto/sha256"
  4. "encoding/hex"
  5. "encoding/json"
  6. "errors"
  7. "fmt"
  8. "io"
  9. "log/slog"
  10. "os"
  11. "path/filepath"
  12. "github.com/ollama/ollama/types/model"
  13. )
  14. type Manifest struct {
  15. SchemaVersion int `json:"schemaVersion"`
  16. MediaType string `json:"mediaType"`
  17. Config Layer `json:"config"`
  18. Layers []Layer `json:"layers"`
  19. filepath string
  20. fi os.FileInfo
  21. digest string
  22. }
  23. func (m *Manifest) Size() (size int64) {
  24. for _, layer := range append(m.Layers, m.Config) {
  25. size += layer.Size
  26. }
  27. return
  28. }
  29. func (m *Manifest) Remove() error {
  30. if err := os.Remove(m.filepath); err != nil {
  31. return err
  32. }
  33. manifests, err := GetManifestPath()
  34. if err != nil {
  35. return err
  36. }
  37. return PruneDirectory(manifests)
  38. }
  39. func (m *Manifest) RemoveLayers() error {
  40. for _, layer := range append(m.Layers, m.Config) {
  41. if layer.Digest != "" {
  42. if err := layer.Remove(); errors.Is(err, os.ErrNotExist) {
  43. slog.Debug("layer does not exist", "digest", layer.Digest)
  44. } else if err != nil {
  45. return err
  46. }
  47. }
  48. }
  49. return nil
  50. }
  51. func ParseNamedManifest(n model.Name) (*Manifest, error) {
  52. if !n.IsFullyQualified() {
  53. return nil, model.Unqualified(n)
  54. }
  55. manifests, err := GetManifestPath()
  56. if err != nil {
  57. return nil, err
  58. }
  59. p := filepath.Join(manifests, n.Filepath())
  60. var m Manifest
  61. f, err := os.Open(p)
  62. if err != nil {
  63. return nil, err
  64. }
  65. defer f.Close()
  66. fi, err := f.Stat()
  67. if err != nil {
  68. return nil, err
  69. }
  70. sha256sum := sha256.New()
  71. if err := json.NewDecoder(io.TeeReader(f, sha256sum)).Decode(&m); err != nil {
  72. return nil, err
  73. }
  74. m.filepath = p
  75. m.fi = fi
  76. m.digest = hex.EncodeToString(sha256sum.Sum(nil))
  77. return &m, nil
  78. }
  79. func WriteManifest(name model.Name, config Layer, layers []Layer) error {
  80. manifests, err := GetManifestPath()
  81. if err != nil {
  82. return err
  83. }
  84. p := filepath.Join(manifests, name.Filepath())
  85. if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
  86. return err
  87. }
  88. f, err := os.Create(p)
  89. if err != nil {
  90. return err
  91. }
  92. defer f.Close()
  93. m := Manifest{
  94. SchemaVersion: 2,
  95. MediaType: "application/vnd.docker.distribution.manifest.v2+json",
  96. Config: config,
  97. Layers: layers,
  98. }
  99. return json.NewEncoder(f).Encode(m)
  100. }
  101. func Manifests() (map[model.Name]*Manifest, error) {
  102. manifests, err := GetManifestPath()
  103. if err != nil {
  104. return nil, err
  105. }
  106. // TODO(mxyng): use something less brittle
  107. matches, err := filepath.Glob(filepath.Join(manifests, "*", "*", "*", "*"))
  108. if err != nil {
  109. return nil, err
  110. }
  111. ms := make(map[model.Name]*Manifest)
  112. for _, match := range matches {
  113. fi, err := os.Stat(match)
  114. if err != nil {
  115. return nil, err
  116. }
  117. if !fi.IsDir() {
  118. rel, err := filepath.Rel(manifests, match)
  119. if err != nil {
  120. slog.Warn("bad filepath", "path", match, "error", err)
  121. continue
  122. }
  123. n := model.ParseNameFromFilepath(rel)
  124. if !n.IsValid() {
  125. slog.Warn("bad manifest name", "path", rel)
  126. continue
  127. }
  128. m, err := ParseNamedManifest(n)
  129. if syntax := &(json.SyntaxError{}); errors.As(err, &syntax) {
  130. slog.Warn("bad manifest", "name", n, "error", err)
  131. continue
  132. } else if err != nil {
  133. return nil, fmt.Errorf("%s: %w", n, err)
  134. }
  135. ms[n] = m
  136. }
  137. }
  138. return ms, nil
  139. }