Commit cbfa78d2 authored by Kirill Smelkov's avatar Kirill Smelkov

*: Handle Git object types as git.ObjectType instead of string

parent 7f349cd9
...@@ -184,20 +184,22 @@ func blob_to_file(g *git.Repository, blob_sha1 Sha1, mode uint32, path string) { ...@@ -184,20 +184,22 @@ func blob_to_file(g *git.Repository, blob_sha1 Sha1, mode uint32, path string) {
// another, so that on backup restore we only have to recreate original tag // another, so that on backup restore we only have to recreate original tag
// 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": {}} func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type git.ObjectType) Sha1 {
func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 { switch obj_type {
if !tag_tree_blob.Contains(obj_type) { case git.ObjectTag, git.ObjectTree, git.ObjectBlob:
// ok
default:
exc.Raisef("%s (%s): cannot encode as commit", sha1, obj_type) exc.Raisef("%s (%s): cannot encode as commit", sha1, obj_type)
} }
// first line in commit msg = object type // first line in commit msg = object type
obj_encoded := obj_type + "\n" obj_encoded := gittypestr(obj_type) + "\n"
var tagged_type string var tagged_type git.ObjectType
var tagged_sha1 Sha1 var tagged_sha1 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 == git.ObjectTag {
tag, tag_obj := xload_tag(g, 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
...@@ -219,7 +221,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 ...@@ -219,7 +221,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1
// | .msg: Tag // | .msg: Tag
// v .tree -> ø // v .tree -> ø
// Commit .parent -> Commit // Commit .parent -> Commit
if tagged_type == "commit" { if tagged_type == git.ObjectCommit {
return zcommit_tree(mktree_empty(), []Sha1{tagged_sha1}, obj_encoded) return zcommit_tree(mktree_empty(), []Sha1{tagged_sha1}, obj_encoded)
} }
...@@ -227,7 +229,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 ...@@ -227,7 +229,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1
// | .msg: Tag // | .msg: Tag
// v .tree -> Tree // v .tree -> Tree
// Tree .parent -> ø // Tree .parent -> ø
if tagged_type == "tree" { if tagged_type == git.ObjectTree {
return zcommit_tree(tagged_sha1, []Sha1{}, obj_encoded) return zcommit_tree(tagged_sha1, []Sha1{}, obj_encoded)
} }
...@@ -235,7 +237,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 ...@@ -235,7 +237,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1
// | .msg: Tag // | .msg: Tag
// v .tree -> Tree* "tagged" -> Blob // v .tree -> Tree* "tagged" -> Blob
// Blob .parent -> ø // Blob .parent -> ø
if tagged_type == "blob" { if tagged_type == git.ObjectBlob {
tree_for_blob := xgitSha1("mktree", RunWith{stdin: fmt.Sprintf("100644 blob %s\ttagged\n", tagged_sha1)}) tree_for_blob := xgitSha1("mktree", RunWith{stdin: fmt.Sprintf("100644 blob %s\ttagged\n", tagged_sha1)})
return zcommit_tree(tree_for_blob, []Sha1{}, obj_encoded) return zcommit_tree(tree_for_blob, []Sha1{}, obj_encoded)
} }
...@@ -244,7 +246,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1 ...@@ -244,7 +246,7 @@ func obj_represent_as_commit(g *git.Repository, sha1 Sha1, obj_type string) Sha1
// | .msg: Tag₂ // | .msg: Tag₂
// v .tree -> ø // v .tree -> ø
// Tag₁ .parent -> Commit₁* // Tag₁ .parent -> Commit₁*
if tagged_type == "tag" { if tagged_type == git.ObjectTag {
commit1 := obj_represent_as_commit(g, 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)
} }
...@@ -274,7 +276,10 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 { ...@@ -274,7 +276,10 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 {
if err != nil { if err != nil {
xraise("invalid encoded format") xraise("invalid encoded format")
} }
if !tag_tree_blob.Contains(obj_type) { switch obj_type {
case "tag", "tree", "blob":
// ok
default:
xraisef("unexpected encoded object type %q", obj_type) xraisef("unexpected encoded object type %q", obj_type)
} }
...@@ -295,7 +300,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 { ...@@ -295,7 +300,7 @@ func obj_recreate_from_commit(g *git.Repository, commit_sha1 Sha1) Sha1 {
if err != nil { if err != nil {
xraisef("encoded tag: %s", err) xraisef("encoded tag: %s", err)
} }
if tag.tagged_type == "tag" { if tag.tagged_type == git.ObjectTag {
if commit.ParentCount() == 0 { if commit.ParentCount() == 0 {
xraise("encoded tag corrupt (tagged is tag but []parent is empty)") xraise("encoded tag corrupt (tagged is tag but []parent is empty)")
} }
...@@ -494,7 +499,11 @@ func cmd_pull_(gb *git.Repository, pullspecv []PullSpec) { ...@@ -494,7 +499,11 @@ 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(gb, sha1, type_) obj_type, ok := gittype(type_)
if !ok {
exc.Raisef("%s: invalid git type in entry %q", backup_refs_work, __)
}
sha1_ = obj_represent_as_commit(gb, sha1, obj_type)
noncommit_seen[sha1] = sha1_ noncommit_seen[sha1] = sha1_
} }
......
...@@ -60,6 +60,15 @@ func XSha1(s string) Sha1 { ...@@ -60,6 +60,15 @@ func XSha1(s string) Sha1 {
return sha1 return sha1
} }
func xgittype(s string) git.ObjectType {
type_, ok := gittype(s)
if !ok {
exc.Raisef("unknown git type %q", s)
}
return type_
}
// verify end-to-end pull-restore // verify end-to-end pull-restore
func TestPullRestore(t *testing.T) { func TestPullRestore(t *testing.T) {
// if something raises -> don't let testing panic - report it as proper error with context. // if something raises -> don't let testing panic - report it as proper error with context.
...@@ -145,7 +154,7 @@ func TestPullRestore(t *testing.T) { ...@@ -145,7 +154,7 @@ func TestPullRestore(t *testing.T) {
// encoding original object should give sha1_ // encoding original object should give sha1_
obj_type := xgit("cat-file", "-t", nc.sha1) obj_type := xgit("cat-file", "-t", nc.sha1)
sha1_ := obj_represent_as_commit(gb, nc.sha1, obj_type) sha1_ := obj_represent_as_commit(gb, nc.sha1, xgittype(obj_type))
if sha1_ != nc.sha1_ { if sha1_ != nc.sha1_ {
t.Fatalf("encode %s -> %s ; want %s", sha1, sha1_, nc.sha1_) t.Fatalf("encode %s -> %s ; want %s", sha1, sha1_, nc.sha1_)
} }
......
...@@ -91,9 +91,8 @@ func (e *UnexpectedObjType) Error() string { ...@@ -91,9 +91,8 @@ func (e *UnexpectedObjType) Error() string {
} }
type Tag struct { type Tag struct {
tagged_type string tagged_type git.ObjectType
tagged_sha1 Sha1 tagged_sha1 Sha1
// TODO msg // TODO msg
} }
...@@ -127,10 +126,16 @@ func (e *TagLoadError) Error() string { ...@@ -127,10 +126,16 @@ func (e *TagLoadError) Error() string {
func tag_parse(tag_raw string) (*Tag, error) { func tag_parse(tag_raw string) (*Tag, error) {
t := Tag{} t := Tag{}
_, err := fmt.Sscanf(tag_raw, "object %s\ntype %s\n", &t.tagged_sha1, &t.tagged_type) tagged_type := ""
_, err := fmt.Sscanf(tag_raw, "object %s\ntype %s\n", &t.tagged_sha1, &tagged_type)
if err != nil { if err != nil {
return nil, errors.New("invalid header") return nil, errors.New("invalid header")
} }
var ok bool
t.tagged_type, ok = gittype(tagged_type)
if !ok {
return nil, fmt.Errorf("invalid tagged type %q", tagged_type)
}
return &t, nil return &t, nil
} }
...@@ -244,3 +249,37 @@ func xcommit_tree2(g *git.Repository, tree Sha1, parents []Sha1, msg string, aut ...@@ -244,3 +249,37 @@ func xcommit_tree2(g *git.Repository, tree Sha1, parents []Sha1, msg string, aut
func xcommit_tree(g *git.Repository, tree Sha1, parents []Sha1, msg string) Sha1 { func xcommit_tree(g *git.Repository, tree Sha1, parents []Sha1, msg string) Sha1 {
return xcommit_tree2(g, tree, parents, msg, AuthorInfo{}, AuthorInfo{}) return xcommit_tree2(g, tree, parents, msg, AuthorInfo{}, AuthorInfo{})
} }
// gittype converts string to git.ObjectType.
//
// Only valid concrete git types are converted successfully.
func gittype(typ string) (git.ObjectType, bool) {
switch typ {
case "commit": return git.ObjectCommit, true
case "tree": return git.ObjectTree, true
case "blob": return git.ObjectBlob, true
case "tag": return git.ObjectTag, true
}
return git.ObjectBad, false
}
// gittypestr converts git.ObjectType to string.
//
// We depend on this conversion being exact and matching how Git encodes it in
// objects. git.ObjectType.String() is different (e.g. "Blob" instead of
// "blob"), and can potentially change over time.
//
// gittypestr expects the type to be valid and concrete - else it panics.
func gittypestr(typ git.ObjectType) string {
switch typ {
case git.ObjectCommit: return "commit"
case git.ObjectTree: return "tree"
case git.ObjectBlob: return "blob"
case git.ObjectTag: return "tag"
}
panic(fmt.Sprintf("git type %#v invalid", typ))
}
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