mirror of
https://codeberg.org/git-pages/git-pages.git
synced 2026-05-14 03:01:48 +00:00
Fix combined partial and incremental updates.
It seems that I forgot to implement incremental update support for partial updates entirely.
This commit is contained in:
@@ -15,7 +15,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/c2h5oh/datasize"
|
||||
"github.com/go-git/go-git/v6/plumbing"
|
||||
"github.com/klauspost/compress/zstd"
|
||||
)
|
||||
|
||||
@@ -52,16 +51,6 @@ func ExtractZstd(
|
||||
return next(ctx, boundArchiveStream(stream))
|
||||
}
|
||||
|
||||
const BlobReferencePrefix = "/git/blobs/"
|
||||
|
||||
type UnresolvedRefError struct {
|
||||
missing []string
|
||||
}
|
||||
|
||||
func (err UnresolvedRefError) Error() string {
|
||||
return fmt.Sprintf("%d unresolved blob references", len(err.missing))
|
||||
}
|
||||
|
||||
func normalizeArchiveMemberName(fileName string) string {
|
||||
// Strip the leading slash and any extraneous path segments.
|
||||
fileName = path.Clean(fileName)
|
||||
@@ -72,21 +61,6 @@ func normalizeArchiveMemberName(fileName string) string {
|
||||
return fileName
|
||||
}
|
||||
|
||||
// Returns a map of git hash to entry. If `manifest` is nil, returns an empty map.
|
||||
func indexManifestByGitHash(manifest *Manifest) map[string]*Entry {
|
||||
index := map[string]*Entry{}
|
||||
for _, entry := range manifest.GetContents() {
|
||||
if hash := entry.GetGitHash(); hash != "" {
|
||||
if _, ok := plumbing.FromHex(hash); ok {
|
||||
index[hash] = entry
|
||||
} else {
|
||||
panic(fmt.Errorf("index: malformed hash: %s", hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func addSymlinkOrBlobReference(
|
||||
manifest *Manifest, fileName string, target string,
|
||||
index map[string]*Entry, missing *[]string,
|
||||
@@ -110,7 +84,7 @@ func ExtractTar(ctx context.Context, reader io.Reader, oldManifest *Manifest) (*
|
||||
var dataBytesRecycled int64
|
||||
var dataBytesTransferred int64
|
||||
|
||||
index := indexManifestByGitHash(oldManifest)
|
||||
index := IndexManifestByGitHash(oldManifest)
|
||||
missing := []string{}
|
||||
manifest := NewManifest()
|
||||
for {
|
||||
@@ -202,7 +176,7 @@ func ExtractZip(ctx context.Context, reader io.Reader, oldManifest *Manifest) (*
|
||||
var dataBytesRecycled int64
|
||||
var dataBytesTransferred int64
|
||||
|
||||
index := indexManifestByGitHash(oldManifest)
|
||||
index := IndexManifestByGitHash(oldManifest)
|
||||
missing := []string{}
|
||||
manifest := NewManifest()
|
||||
for _, file := range archive.File {
|
||||
|
||||
@@ -145,6 +145,21 @@ func AddProblem(manifest *Manifest, pathName, format string, args ...any) error
|
||||
return fmt.Errorf("%s: %s", pathName, cause)
|
||||
}
|
||||
|
||||
// Returns a map of git hash to entry. If `manifest` is nil, returns an empty map.
|
||||
func IndexManifestByGitHash(manifest *Manifest) map[string]*Entry {
|
||||
index := map[string]*Entry{}
|
||||
for _, entry := range manifest.GetContents() {
|
||||
if hash := entry.GetGitHash(); hash != "" {
|
||||
if _, ok := plumbing.FromHex(hash); ok {
|
||||
index[hash] = entry
|
||||
} else {
|
||||
panic(fmt.Errorf("index: malformed hash: %s", hash))
|
||||
}
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func IsEntryRegularFile(entry *Entry) bool {
|
||||
return entry.GetType() == Type_InlineFile ||
|
||||
entry.GetType() == Type_ExternalFile
|
||||
|
||||
22
src/patch.go
22
src/patch.go
@@ -30,8 +30,12 @@ func ApplyTarPatch(manifest *Manifest, reader io.Reader, parents CreateParentsMo
|
||||
children map[string]*Node
|
||||
}
|
||||
|
||||
// Index the manifest for incremental update operations.
|
||||
index := IndexManifestByGitHash(manifest)
|
||||
missing := []string{}
|
||||
|
||||
// Extract the manifest contents (which is using a flat hash map) into a directory tree
|
||||
// so that recursive delete operations have O(1) complexity. s
|
||||
// so that recursive delete operations have O(1) complexity.
|
||||
var root *Node
|
||||
sortedNames := slices.Sorted(maps.Keys(manifest.GetContents()))
|
||||
for _, name := range sortedNames {
|
||||
@@ -107,8 +111,16 @@ func ApplyTarPatch(manifest *Manifest, reader io.Reader, parents CreateParentsMo
|
||||
entry: NewManifestEntry(Type_InlineFile, fileData),
|
||||
}
|
||||
case tar.TypeSymlink:
|
||||
node.children[fileName] = &Node{
|
||||
entry: NewManifestEntry(Type_Symlink, []byte(header.Linkname)),
|
||||
if hash, found := strings.CutPrefix(header.Linkname, BlobReferencePrefix); found {
|
||||
if entry, found := index[hash]; found {
|
||||
node.children[fileName] = &Node{entry: entry}
|
||||
} else {
|
||||
missing = append(missing, hash)
|
||||
}
|
||||
} else {
|
||||
node.children[fileName] = &Node{
|
||||
entry: NewManifestEntry(Type_Symlink, []byte(header.Linkname)),
|
||||
}
|
||||
}
|
||||
case tar.TypeDir:
|
||||
node.children[fileName] = &Node{
|
||||
@@ -129,6 +141,10 @@ func ApplyTarPatch(manifest *Manifest, reader io.Reader, parents CreateParentsMo
|
||||
}
|
||||
}
|
||||
|
||||
if len(missing) > 0 {
|
||||
return UnresolvedRefError{missing}
|
||||
}
|
||||
|
||||
// Repopulate manifest contents with the updated directory tree.
|
||||
var traverse func([]string, *Node)
|
||||
traverse = func(segments []string, node *Node) {
|
||||
|
||||
@@ -10,6 +10,16 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const BlobReferencePrefix = "/git/blobs/"
|
||||
|
||||
type UnresolvedRefError struct {
|
||||
missing []string
|
||||
}
|
||||
|
||||
func (err UnresolvedRefError) Error() string {
|
||||
return fmt.Sprintf("%d unresolved blob references", len(err.missing))
|
||||
}
|
||||
|
||||
type UpdateOutcome int
|
||||
|
||||
const (
|
||||
|
||||
Reference in New Issue
Block a user