layer.go 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package server
  2. import (
  3. "crypto/sha256"
  4. "fmt"
  5. "io"
  6. "os"
  7. )
  8. type Layer struct {
  9. MediaType string `json:"mediaType"`
  10. Digest string `json:"digest"`
  11. Size int64 `json:"size"`
  12. From string `json:"from,omitempty"`
  13. Intermediate bool `json:"intermediate,omitempty"`
  14. MergeBase string `json:"merge_base,omitempty"`
  15. message string
  16. }
  17. func NewLayer(r io.Reader, mediatype string) (*Layer, error) {
  18. blobs, err := GetBlobsPath("")
  19. if err != nil {
  20. return nil, err
  21. }
  22. temp, err := os.CreateTemp(blobs, "sha256-")
  23. if err != nil {
  24. return nil, err
  25. }
  26. defer temp.Close()
  27. defer os.Remove(temp.Name())
  28. sha256sum := sha256.New()
  29. n, err := io.Copy(io.MultiWriter(temp, sha256sum), r)
  30. if err != nil {
  31. return nil, err
  32. }
  33. if err := temp.Close(); err != nil {
  34. return nil, err
  35. }
  36. digest := fmt.Sprintf("sha256:%x", sha256sum.Sum(nil))
  37. blob, err := GetBlobsPath(digest)
  38. if err != nil {
  39. return nil, err
  40. }
  41. status := "using existing layer"
  42. if _, err := os.Stat(blob); err != nil {
  43. status = "creating new layer"
  44. if err := os.Rename(temp.Name(), blob); err != nil {
  45. return nil, err
  46. }
  47. }
  48. return &Layer{
  49. MediaType: mediatype,
  50. Digest: digest,
  51. Size: n,
  52. message: fmt.Sprintf("%s %s", status, digest),
  53. }, nil
  54. }
  55. func NewLayerFromLayer(digest, mediatype, from string) (*Layer, error) {
  56. blob, err := GetBlobsPath(digest)
  57. if err != nil {
  58. return nil, err
  59. }
  60. fi, err := os.Stat(blob)
  61. if err != nil {
  62. return nil, err
  63. }
  64. return &Layer{
  65. MediaType: mediatype,
  66. Digest: digest,
  67. Size: fi.Size(),
  68. From: from,
  69. message: fmt.Sprintf("using existing layer %s", digest),
  70. }, nil
  71. }
  72. func (l *Layer) Open() (*os.File, error) {
  73. blob, err := GetBlobsPath(l.Digest)
  74. if err != nil {
  75. return nil, err
  76. }
  77. return os.Open(blob)
  78. }