[mirror] Scalable static site server for Git forges (like GitHub Pages)

Factor out functions to create and fill a manifest. NFCI

+56 -51
+13 -43
src/extract.go
··· 13 13 14 14 "github.com/c2h5oh/datasize" 15 15 "github.com/klauspost/compress/zstd" 16 - "google.golang.org/protobuf/proto" 17 16 ) 18 17 19 18 var ErrArchiveTooLarge = errors.New("archive too large") ··· 46 45 func ExtractTar(reader io.Reader) (*Manifest, error) { 47 46 archive := tar.NewReader(reader) 48 47 49 - manifest := Manifest{ 50 - Contents: map[string]*Entry{ 51 - "": {Type: Type_Directory.Enum()}, 52 - }, 53 - } 48 + manifest := NewManifest() 54 49 for { 55 50 header, err := archive.Next() 56 51 if err == io.EOF { ··· 70 65 } 71 66 } 72 67 73 - manifestEntry := Entry{} 74 68 switch header.Typeflag { 75 69 case tar.TypeReg: 76 70 fileData, err := io.ReadAll(archive) 77 71 if err != nil { 78 72 return nil, fmt.Errorf("tar: %s: %w", fileName, err) 79 73 } 80 - 81 - manifestEntry.Type = Type_InlineFile.Enum() 82 - manifestEntry.Data = fileData 83 - manifestEntry.Transform = Transform_Identity.Enum() 84 - manifestEntry.OriginalSize = proto.Int64(header.Size) 85 - manifestEntry.CompressedSize = proto.Int64(header.Size) 86 - 74 + AddFile(manifest, fileName, fileData) 87 75 case tar.TypeSymlink: 88 - manifestEntry.Type = Type_Symlink.Enum() 89 - manifestEntry.Data = []byte(header.Linkname) 90 - manifestEntry.Transform = Transform_Identity.Enum() 91 - manifestEntry.OriginalSize = proto.Int64(header.Size) 92 - manifestEntry.CompressedSize = proto.Int64(header.Size) 93 - 76 + AddSymlink(manifest, fileName, header.Linkname) 94 77 case tar.TypeDir: 95 - manifestEntry.Type = Type_Directory.Enum() 96 - fileName = strings.TrimSuffix(fileName, "/") 97 - 78 + AddDirectory(manifest, fileName) 98 79 default: 99 - AddProblem(&manifest, fileName, "unsupported type '%c'", header.Typeflag) 80 + AddProblem(manifest, fileName, "unsupported type '%c'", header.Typeflag) 100 81 continue 101 82 } 102 - manifest.Contents[fileName] = &manifestEntry 103 83 } 104 - return &manifest, nil 84 + return manifest, nil 105 85 } 106 86 107 87 func ExtractZip(reader io.Reader) (*Manifest, error) { ··· 128 108 ) 129 109 } 130 110 131 - manifest := Manifest{ 132 - Contents: map[string]*Entry{ 133 - "": {Type: Type_Directory.Enum()}, 134 - }, 135 - } 111 + manifest := NewManifest() 136 112 for _, file := range archive.File { 137 - manifestEntry := Entry{} 138 - if !strings.HasSuffix(file.Name, "/") { 113 + if strings.HasSuffix(file.Name, "/") { 114 + AddDirectory(manifest, file.Name) 115 + } else { 139 116 fileReader, err := file.Open() 140 117 if err != nil { 141 118 return nil, err ··· 148 125 } 149 126 150 127 if file.Mode()&os.ModeSymlink != 0 { 151 - manifestEntry.Type = Type_Symlink.Enum() 128 + AddSymlink(manifest, file.Name, string(fileData)) 152 129 } else { 153 - manifestEntry.Type = Type_InlineFile.Enum() 130 + AddFile(manifest, file.Name, fileData) 154 131 } 155 - manifestEntry.Data = fileData 156 - manifestEntry.Transform = Transform_Identity.Enum() 157 - manifestEntry.OriginalSize = proto.Int64(int64(file.UncompressedSize64)) 158 - manifestEntry.CompressedSize = proto.Int64(int64(file.UncompressedSize64)) 159 - } else { 160 - manifestEntry.Type = Type_Directory.Enum() 161 132 } 162 - manifest.Contents[strings.TrimSuffix(file.Name, "/")] = &manifestEntry 163 133 } 164 - return &manifest, nil 134 + return manifest, nil 165 135 }
+4 -8
src/fetch.go
··· 96 96 97 97 // Create a manifest for the tree object corresponding to `branch`, but do not populate it 98 98 // with data yet; instead, record all the blobs we'll need. 99 - manifest := &Manifest{ 100 - RepoUrl: proto.String(repoURL), 101 - Branch: proto.String(branch), 102 - Commit: proto.String(ref.Hash().String()), 103 - Contents: map[string]*Entry{ 104 - "": {Type: Type_Directory.Enum()}, 105 - }, 106 - } 99 + manifest := NewManifest() 100 + manifest.RepoUrl = proto.String(repoURL) 101 + manifest.Branch = proto.String(branch) 102 + manifest.Commit = proto.String(ref.Hash().String()) 107 103 blobsNeeded := map[plumbing.Hash]*Entry{} 108 104 for { 109 105 name, entry, err := walker.Next()
+39
src/manifest.go
··· 36 36 }) 37 37 ) 38 38 39 + func NewManifest() *Manifest { 40 + return &Manifest{ 41 + Contents: map[string]*Entry{ 42 + "": {Type: Type_Directory.Enum()}, 43 + }, 44 + } 45 + } 46 + 39 47 func IsManifestEmpty(manifest *Manifest) bool { 40 48 if len(manifest.Contents) > 1 { 41 49 return false ··· 80 88 manifest = &Manifest{} 81 89 err = proto.Unmarshal(data, manifest) 82 90 return 91 + } 92 + 93 + func NewManifestEntry(type_ Type, data []byte) *Entry { 94 + entry := &Entry{} 95 + entry.Type = type_.Enum() 96 + if data != nil { 97 + entry.Data = data 98 + entry.Transform = Transform_Identity.Enum() 99 + entry.OriginalSize = proto.Int64(int64(len(data))) 100 + entry.CompressedSize = proto.Int64(int64(len(data))) 101 + } 102 + return entry 103 + } 104 + 105 + func AddFile(manifest *Manifest, path string, data []byte) *Entry { 106 + entry := NewManifestEntry(Type_InlineFile, data) 107 + manifest.Contents[path] = entry 108 + return entry 109 + } 110 + 111 + func AddSymlink(manifest *Manifest, path string, target string) *Entry { 112 + entry := NewManifestEntry(Type_Symlink, []byte(target)) 113 + manifest.Contents[path] = entry 114 + return entry 115 + } 116 + 117 + func AddDirectory(manifest *Manifest, path string) *Entry { 118 + path = strings.TrimSuffix(path, "/") 119 + entry := NewManifestEntry(Type_Directory, nil) 120 + manifest.Contents[path] = entry 121 + return entry 83 122 } 84 123 85 124 func AddProblem(manifest *Manifest, path, format string, args ...any) error {