--- a/internal/cli/cmd_log.go
+++ b/internal/cli/cmd_log.go
@@ -1,161 +1,357 @@
package cli
import (
"fmt"
"
+strings"
+ "
time"
"arche/internal/object"
"arche/internal/revset"
"github.com/spf13/cobra"
)
var (
logLimit int
logOps bool
logShowSecret bool
logWhere string
+ logGraph bool
-)
+)
+
+
+type logCommit struct {
+ id [32]byte
+ commit *object.Commit
+ phase object.Phase
+ parents [][32]byte
+}
var logCmd = &cobra.Command{
Use: "log",
Short: "Show the commit DAG",
Long: `Walk the commit graph backwards from HEAD (and all bookmarks) and display
each commit in reverse chronological order.
With --ops, show the operation log instead (equivalent to 'arche op log').`,
RunE: func(cmd *cobra.Command, args []string) error {
r := openRepo()
defer r.Close()
if logOps {
ops, err := r.Store.ListOperations(logLimit)
if err != nil {
return err
}
if len(ops) == 0 {
fmt.Println("No operations recorded.")
return nil
}
for _, op := range ops {
ts := time.Unix(op.Timestamp, 0).Format("2006-01-02 15:04:05")
if op.Metadata != "" {
fmt.Printf("#%-4d %-14s %s %s\n", op.Seq, op.Kind, ts, op.Metadata)
} else {
fmt.Printf("#%-4d %-14s %s\n", op.Seq, op.Kind, ts)
}
}
return nil
}
var whereFilter revset.Func
if logWhere != "" {
var err error
whereFilter, err = revset.Parse(logWhere)
if err != nil {
return err
}
}
+bms, _ := r.S
-t
+t
+ore.L
-i
+i
-p
+stBookmark
-s
+s
+()
+ bmIndex
- := make(map[[32]byte]
+ := make(map[[32]byte]
+[]string)
+ for _,
-b
+b
+m := range bms {
+ bmIndex[bm.C
-o
+o
+mmitID] = append(bmIndex[bm.C
-o
+o
-l
+mmitID], bm.Name
-)
-
+)
+
-_,
+}
+ var
-h
+curH
eadID
+ [32]byte
+ if _, id
, err := r.HeadCommit()
-
- if
+;
err == nil {
-tips[h
+curH
eadID
-]
=
-true
+id
}
-bm
+tip
s
-, _
:=
-r.S
+make(map[[32]by
t
+e]b
o
+ol)
+ if cu
r
+H
e
-.L
+adID != ([32]byte{}) {
+ t
i
+p
s
+[curHeadID] =
t
-Bookma
r
-ks()
+ue
+ }
for _, bm := range bms {
tips[bm.CommitID] = true
}
-s
+typ
e
-e
+ commitI
n
+fo = logCommit
+ allByID
:= ma
-k
+p[[32]byt
e
-(
+]*commitInfo{}
+ {
+ seen :=
map[[32]byte]bool
-)
+{}
+
queue := make([][32]byte, 0, len(tips))
+
for id := range tips {
+
queue = append(queue, id)
-}
-
- bmIndex := make(map[[32]byte][]string)
- for _, bm := range bms {
- bmIndex[bm.CommitID] = append(bmIndex[bm.CommitID], bm.Name)
-
}
-var curHeadID [32]byte
- if _, id, err := r.HeadCommit(); err == nil {
- curHeadID = id
- }
-
- count := 0
-
for len(queue) > 0
-&& (logLimit <= 0 || count < logLimit)
{
+
id := queue[0]
+
queue = queue[1:]
+
if seen[id] {
+
continue
+
}
+
seen[id] = true
-
+
c, err := r.ReadCommit(id)
+
if err != nil {
+
continue
-}
-
- if !logShowSecret {
+}
phase, _ := r.Store.GetPhase(id)
if
+ !logShowSecret &&
phase == object.PhaseSecret {
for _, p := range c.Parents {
if !seen[p] {
queue = append(queue, p)
}
}
continue
}
-}
-
-
if whereFilter != nil
-{
- phase, _ := r.Store.GetPhase(id)
- if
+&&
!whereFilter(id, c, phase) {
for _, p := range c.Parents {
if !seen[p] {
queue = append(queue, p)
}
}
continue
}
+ allByID[id] = &commitInfo{id: id, commit: c, phase: phase, parents: c.Parents
}
-
+
+for _,
p
+ :=
r
-i
+ange c.Pare
nt
+s {
+ if !seen[p] {
+ queue = append(queue, p)
+ }
+ }
+ }
+ }
+
+ child
Co
-m
+unt :=
m
+ap[[32]byte]
i
+n
t
-(
+{}
+ for _, c
i
-d
+ := range allByID {
+ for _
,
+p := range
c
+i.parents {
+ if _
,
-bm
+ok := allBy
I
+D[p]; ok {
+ childCou
n
+t[p]++
+ }
+ }
+ }
+ topoQueue := make([][32]byte, 0, len(allByID))
+ for i
d
+ := rang
e
-x
+ allByID {
+ if childCount
[id]
+ == 0 {
+ topoQueue = append(topoQueue
,
+id)
+ }
+ }
+ var ordered []
c
+ommitInfo
+ for len(topoQ
u
+eue) > 0 {
+ best := 0
+ fo
r
-H
+ i := 1; i < len(topoQu
e
+ue); i++ {
+
a
-d
+ := allBy
ID
+[topoQueue[i]].commit.Author.Timestamp
+ b
+:
=
+ allByID[topoQueue[best]].commit.Author.Timestamp
+ if a.After(b) {
+ best
= i
+
+ }
+ }
+ i
d
+ := topoQueue[best]
+ topoQueue[best] = topoQueue[len(topoQueue
)
+-1]
-c
+t
o
+poQue
u
+e = topoQueue[:le
n
+(
t
-++
+opoQueue)-1]
+ci := allByID[id]
+ ordered = append(ordered, *ci)
+
for _, p := range c
+i
.
-P
+p
arents {
if
+_, ok := allByID[p];
!
-s
+ok {
+ continu
e
-e
+
+ }
+ childCou
n
+t
[p]
+--
+ if childCount[p] == 0
{
-q
+topoQ
ueue = append(
-q