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 {
// object and tagged object is kept there in repo thanks to it being reachable
// through created commit.
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) {
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 {
// below the code layout is mainly for tag type, and we hook tree and blob
// types handling into that layout
if obj_type == "tag" {
tag, tag_raw := xload_tag(sha1)
tag, tag_obj := xload_tag(g, sha1)
tagged_type = tag.tagged_type
tagged_sha1 = tag.tagged_sha1
obj_encoded += tag_raw
obj_encoded += String(tag_obj.Data())
} else {
// for tree/blob we only care that object stays reachable
tagged_type = obj_type
......@@ -278,7 +278,7 @@ func obj_represent_as_commit(sha1 Sha1, obj_type string) Sha1 {
// v .tree -> ø
// Tag₁ .parent -> Commit₁*
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)
}
......@@ -332,7 +332,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) {
}
// 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 {
xraisef("encoded tag corrupt (reencoded as %s)", commit_sha1_)
}
......@@ -518,7 +518,7 @@ func cmd_pull_(gb *git.Repository, pullspecv []PullSpec) {
var seen bool
sha1_, seen = noncommit_seen[sha1]
if !seen {
sha1_ = obj_represent_as_commit(sha1, type_)
sha1_ = obj_represent_as_commit(gb, sha1, type_)
noncommit_seen[sha1] = sha1_
}
......
......@@ -84,16 +84,21 @@ type Tag struct {
}
// 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})
if gerr != nil {
raise(&TagLoadError{tag_sha1, gerr})
}
tag, err := tag_parse(tag_raw)
//
// Reasons why not use g.LookupTag():
// - we need to get not only parsed tag object, but also its raw content
// (libgit2 drops raw data after parsing object)
// - we need to have tag_parse() -- a way to parse object from a buffer
// (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 {
raise(&TagLoadError{tag_sha1, err})
}
return tag, tag_raw
return tag, tag_obj
}
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