From 9fd13f759ab9d847c50a1caf5fb27285e278b8e5 Mon Sep 17 00:00:00 2001 From: Quentin Dufour Date: Wed, 21 Apr 2021 22:29:17 +0200 Subject: [PATCH] Find HEAD is implemented --- commit.go | 132 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 109 insertions(+), 23 deletions(-) diff --git a/commit.go b/commit.go index a97762d..27525d2 100644 --- a/commit.go +++ b/commit.go @@ -2,41 +2,58 @@ package main import ( "encoding/json" + "fmt" "log" + "time" "io/ioutil" "path/filepath" ) +type Empty struct{} +var empty Empty + type RepoCommits struct { Config configCollect CommitDesc map[string]string - CommitContent map[string]Commit + CommitContent map[string]*CommitNode Head *CommitNode + Root *CommitNode } type CommitNode struct { - Parents []*CommitNode - Children []*CommitNode + Parents map[*CommitNode]Empty + Children map[*CommitNode]Empty Content Commit } type Commit struct { - CommitId string `json:"commit_id"` - RootId string `json:"root_id"` - RepoId string `json:"repo_id"` - CreatorName string `json:"creator_name"` - Creator string `json:"creator"` - Description string `json:"description"` - Ctime uint64 `json:"ctime"` - ParentId string `json:"parent_id"` - SecondParentId string `json:"second_parent_id"` - RepoName string `json:"repo_name"` - RepoDesc string `json:"repo_desc"` - RepoCategory string `json:"repo_category"` + CommitId *string `json:"commit_id"` + RootId *string `json:"root_id"` + RepoId *string `json:"repo_id"` + CreatorName *string `json:"creator_name"` + Creator *string `json:"creator"` + Description *string `json:"description"` + Ctime int64 `json:"ctime"` + ParentId *string `json:"parent_id"` + SecondParentId *string `json:"second_parent_id"` + RepoName *string `json:"repo_name"` + RepoDesc *string `json:"repo_desc"` + RepoCategory *string `json:"repo_category"` NoLocalHistory int `json:"no_local_history"` Version int `json:"version"` } +func (c* Commit) String() string { + return fmt.Sprintf(`RootId: %s +CreatorName: %s +Creator: %s +Description: %s +Ctime: %s +RepoName: %s +RepoDesc: %s +`, *c.RootId, *c.CreatorName, *c.Creator, *c.Description, time.Unix(c.Ctime, 0), *c.RepoName, *c.RepoDesc) +} + func cmdCommit(config configCollect) { rc := NewRepoCommits(config) @@ -44,20 +61,21 @@ func cmdCommit(config configCollect) { rc.PrintDescs() rc.CollectContent() - //rc.BuildGraph() + rc.BuildGraph() + rc.FindHead() + rc.PrintHead() } func NewRepoCommits (config configCollect) *RepoCommits { rc := new(RepoCommits) rc.Config = config rc.CommitDesc = make(map[string]string) - rc.CommitContent = make(map[string]Commit) + rc.CommitContent = make(map[string]*CommitNode) return rc } func (rc* RepoCommits) CollectDescs() { baseFolder := filepath.Join(rc.Config.Storage, "commits", rc.Config.RepoId) - log.Println(baseFolder) layer1, err := ioutil.ReadDir(baseFolder) if err != nil { log.Fatal(err) } for _, l1 := range layer1 { @@ -73,7 +91,7 @@ func (rc* RepoCommits) CollectDescs() { } func (rc* RepoCommits) PrintDescs() { - limit := 10 + /*limit := 10 for id, path := range rc.CommitDesc { log.Println(id, path) limit = limit - 1 @@ -81,18 +99,86 @@ func (rc* RepoCommits) PrintDescs() { log.Println("Too many commits, output has been truncated") break } - } + }*/ log.Println("Repo", rc.Config.RepoId, "contains", len(rc.CommitDesc), "commits") } +func NewCommitNode(c Commit) *CommitNode { + cn := new(CommitNode) + cn.Content = c + cn.Parents = make(map[*CommitNode]Empty) + cn.Children = make(map[*CommitNode]Empty) + + return cn +} + func (rc* RepoCommits) CollectContent() { for id, path := range rc.CommitDesc { data, err := ioutil.ReadFile(path) if err != nil { log.Fatal(err) } - var c Commit + var c Commit; json.Unmarshal(data, &c) - rc.CommitContent[id] = c - log.Println(rc.CommitContent[id]) + rc.CommitContent[id] = NewCommitNode(c) } } + +func (rc* RepoCommits) BuildGraph() *CommitNode { + for _, cn := range rc.CommitContent { + if cn.Content.ParentId == nil && cn.Content.SecondParentId == nil { + if rc.Root == nil { + rc.Root = cn + } else { + log.Fatal("More than one root commit has been found") + } + } + + if cn.Content.ParentId != nil { + parentCn := rc.CommitContent[*cn.Content.ParentId] + cn.Parents[parentCn] = empty + parentCn.Children[cn] = empty + } + + if cn.Content.SecondParentId != nil { + parentCn := rc.CommitContent[*cn.Content.SecondParentId] + cn.Parents[parentCn] = empty + parentCn.Children[cn] = empty + } + } + + if rc.Root == nil { + log.Fatal("Root commit has not been found") + } + + return rc.Root +} + +func (rc* RepoCommits) FindHead() *CommitNode { + toProcess := make(map[*CommitNode]Empty) + toProcess[rc.Root] = empty + + for i := 0; i < len(rc.CommitContent) && len(toProcess) > 0; i++ { + nextToProcess := make(map[*CommitNode]Empty) + for cn, _ := range toProcess { + for ccn, _ := range cn.Children { + nextToProcess[ccn] = empty + } + if len(cn.Children) == 0 { + if rc.Head == nil { + rc.Head = cn + } else { + log.Fatal("More than one HEAD has been found") + } + } + } + + toProcess = nextToProcess + } + + if rc.Head == nil { log.Fatal("No HEAD has been found") } + return rc.Head +} + +func (rc* RepoCommits) PrintHead() { + log.Println(rc.Head.Content.String()) +}