Skip to content

Commit

Permalink
implement reflog (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
JunNishimura committed Jun 15, 2023
1 parent dfdb3e8 commit 0f516e9
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 19 deletions.
36 changes: 17 additions & 19 deletions cmd/reflog.go
Original file line number Diff line number Diff line change
@@ -1,40 +1,38 @@
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
"fmt"

"github.com/JunNishimura/Goit/internal/store"
"github.com/spf13/cobra"
)

// reflogCmd represents the reflog command
var reflogCmd = &cobra.Command{
Use: "reflog",
Short: "A brief description of your command",
Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:
Short: "manage reference logs",
Long: "manage reference logs",
PreRunE: func(cmd *cobra.Command, args []string) error {
if client.RootGoitPath == "" {
return ErrGoitNotInitialized
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
reflog, err := store.NewReflog(client.RootGoitPath, client.Head, client.Refs)
if err != nil {
return fmt.Errorf("fail to get reflog: %w", err)
}

reflog.Show()

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("reflog called")
return nil
},
}

func init() {
rootCmd.AddCommand(reflogCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// reflogCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// reflogCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
123 changes: 123 additions & 0 deletions internal/store/reflog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package store

import (
"bufio"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/JunNishimura/Goit/internal/log"
"github.com/JunNishimura/Goit/internal/sha"
"github.com/fatih/color"
)

type logRecord struct {
hash sha.SHA1
isHead bool
references []string
recType log.RecordType
message string
}

type Reflog struct {
records []*logRecord
}

func NewReflog(rootGoitPath string, head *Head, refs *Refs) (*Reflog, error) {
reflog := newReflog()
if err := reflog.load(rootGoitPath, head, refs); err != nil {
return nil, err
}

return reflog, nil
}

func newReflog() *Reflog {
return &Reflog{
records: make([]*logRecord, 0),
}
}

func (r *Reflog) load(rootGoitPath string, head *Head, refs *Refs) error {
headPath := filepath.Join(rootGoitPath, "logs", "HEAD")
f, err := os.Open(headPath)
if err != nil {
return fmt.Errorf("fail to open %s: %w", headPath, err)
}
defer f.Close()

scanner := bufio.NewScanner(f)
for scanner.Scan() {
record := &logRecord{
references: make([]string, 0),
}

text := scanner.Text()

// extract hash
sp1 := strings.SplitN(text, " ", 3)
if len(sp1) != 3 {
continue
}
if sp1[1] == strings.Repeat("0", 40) {
record.hash = nil
} else {
hash, err := sha.ReadHash(sp1[1])
if err != nil {
return fmt.Errorf("fail to read hash %s: %w", sp1[1], err)
}
record.hash = hash

// references
if head.Commit.Hash.String() == sp1[1] {
record.isHead = true
}
branches := refs.getBranchesByHash(hash)
for _, branch := range branches {
record.references = append(record.references, color.GreenString(branch.Name))
}
}

// extract recType
sp2 := strings.Split(sp1[2], "\t")
if len(sp2) != 2 {
continue
}
sp3 := strings.Split(sp2[1], ": ")
if len(sp3) != 2 {
continue
}
recType := log.NewRecordType(sp3[0])
if recType == log.UndefinedRecord {
continue
}
record.recType = recType
record.message = sp3[1]

r.records = append(r.records, record)
}

return nil
}

func (r *Reflog) Show() {
for i := range r.records {
idx := len(r.records) - i - 1
record := r.records[idx]

var referenceString string
if len(record.references) > 0 {
referenceString = strings.Join(record.references, ", ")
}
if record.isHead {
referenceString = color.BlueString("HEAD -> ") + referenceString
}

if referenceString == "" {
fmt.Printf("%s HEAD:{%d}: %s: %s\n", color.YellowString(record.hash.String()[:7]), i, record.recType, record.message)
} else {
fmt.Printf("%s (%s) HEAD:{%d}: %s: %s\n", color.YellowString(record.hash.String()[:7]), referenceString, i, record.recType, record.message)
}
}
}

0 comments on commit 0f516e9

Please sign in to comment.