Commit 5b1cdca3 authored by Kirill Smelkov's avatar Kirill Smelkov

Switch xload_tag() too work without spawning Git subprocess

We can reuse ReadObject() like for blob_to_file().

We cannot drop xload_tag() in favor of Repository.LookupTag() because
upon tag loading we need to have not only parsed tag, but also its raw
content for encoding in another object.

Time for restoring kirr/slapos.git from lab.nexedi.com backup

before: 8.9s
after:  7.4s

( it goes down because on restore restored tags are reencoded again to
  verify restoration was ok. Pulling time should go down appropriately
  as well )
parent fbd72c02
...@@ -218,7 +218,7 @@ func xcommit_tree(tree Sha1, parents []Sha1, msg string) Sha1 { ...@@ -218,7 +218,7 @@ func xcommit_tree(tree Sha1, parents []Sha1, msg string) Sha1 {
// object and tagged object is kept there in repo thanks to it being reachable // object and tagged object is kept there in repo thanks to it being reachable
// through created commit. // through created commit.
var tag_tree_blob = StrSet{"tag": {}, "tree": {}, "blob": {}} var tag_tree_blob = StrSet{"tag": {}, "tree": {}, "blob": {}}
func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 { func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 {
if !tag_tree_blob.Contains(obj_type) { if !tag_tree_blob.Contains(obj_type) {
raisef("%s (%s): cannot encode as commit", sha1, obj_type) raisef("%s (%s): cannot encode as commit", sha1, obj_type)
} }
...@@ -231,10 +231,10 @@ func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 { ...@@ -231,10 +231,10 @@ func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 {
// below the code layout is mainly for tag type, and we hook tree and blob // below the code layout is mainly for tag type, and we hook tree and blob
// types handling into that layout // types handling into that layout
if obj_type == "tag" { if obj_type == "tag" {
tag, tag_raw := xload_tag(sha1) tag, tag_obj := xload_tag(g, sha1)
tagged_type = tag.tagged_type tagged_type = tag.tagged_type
tagged_sha1 = tag.tagged_sha1 tagged_sha1 = tag.tagged_sha1
obj_encoded += tag_raw obj_encoded += String(tag_obj.Data())
} else { } else {
// for tree/blob we only care that object stays reachable // for tree/blob we only care that object stays reachable
tagged_type = obj_type tagged_type = obj_type
...@@ -278,7 +278,7 @@ func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 { ...@@ -278,7 +278,7 @@ func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 {
// v .tree -> ø // v .tree -> ø
// Tag₁ .parent -> Commit₁* // Tag₁ .parent -> Commit₁*
if tagged_type == "tag" { if tagged_type == "tag" {
commit1 := obj_represent_as_commit(tagged_sha1, tagged_type) commit1 := obj_represent_as_commit(g, tagged_sha1, tagged_type)
return zcommit_tree(mktree_empty(), []Sha1{commit1}, obj_encoded) return zcommit_tree(mktree_empty(), []Sha1{commit1}, obj_encoded)
} }
...@@ -332,7 +332,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) { ...@@ -332,7 +332,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) {
} }
// verify consistency via re-encoding tag again // verify consistency via re-encoding tag again
commit_sha1_ := obj_represent_as_commit(tag_sha1, "tag") commit_sha1_ := obj_represent_as_commit(g, tag_sha1, "tag")
if commit_sha1_ != commit_sha1 { if commit_sha1_ != commit_sha1 {
xraisef("encoded tag corrupt (reencoded as %s)", commit_sha1_) xraisef("encoded tag corrupt (reencoded as %s)", commit_sha1_)
} }
...@@ -518,7 +518,7 @@ func cmd_pull_(gb *git.Repository, pullspecv []PullSpec) { ...@@ -518,7 +518,7 @@ func cmd_pull_(gb *git.Repository, pullspecv []PullSpec) {
var seen bool var seen bool
sha1_, seen = noncommit_seen[sha1] sha1_, seen = noncommit_seen[sha1]
if !seen { if !seen {
sha1_ = obj_represent_as_commit(sha1, type_) sha1_ = obj_represent_as_commit(gb, sha1, type_)
noncommit_seen[sha1] = sha1_ noncommit_seen[sha1] = sha1_
} }
......
...@@ -84,16 +84,21 @@ type Tag struct { ...@@ -84,16 +84,21 @@ type Tag struct {
} }
// load/parse Tag // load/parse Tag
func xload_tag(tag_sha1 Sha1) (tag *Tag, tag_raw string) { //
gerr, tag_raw, _ := ggit("cat-file", "tag", tag_sha1, RunWith{raw: true}) // Reasons why not use g.LookupTag():
if gerr != nil { // - we need to get not only parsed tag object, but also its raw content
raise(&TagLoadError{tag_sha1, gerr}) // (libgit2 drops raw data after parsing object)
} // - we need to have tag_parse() -- a way to parse object from a buffer
tag, err := tag_parse(tag_raw) // (libgit2 does not provide such functionality at all)
func xload_tag(g *git.Repository, tag_sha1 Sha1) (tag *Tag, tag_obj *git.OdbObject) {
tag_obj, err := ReadObject(g, tag_sha1, git.ObjectTag)
raiseif(err)
tag, err = tag_parse(String(tag_obj.Data()))
if err != nil { if err != nil {
raise(&TagLoadError{tag_sha1, err}) raise(&TagLoadError{tag_sha1, err})
} }
return tag, tag_raw return tag, tag_obj
} }
type TagLoadError struct { type TagLoadError struct {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment