marks.go
package main
import (
"bufio"
"fmt"
"io"
"os"
)
type markedChange struct {
mark int
state string
}
type Marks struct {
marks int
changes []markedChange
}
func (m *Marks) Next() int {
m.marks++
return m.marks
}
func (m *Marks) MarkChanges(changes []change) {
// Make a lookup table for existing marks, and make sure we don't
// reuse them.
stateToMark := make(map[string]int)
for _, mc := range m.changes {
stateToMark[mc.state] = mc.mark
if mc.mark > m.marks {
m.marks = mc.mark
}
}
for i := range changes {
if mark, ok := stateToMark[changes[i].State]; ok {
changes[i].mark = mark
changes[i].exported = true
} else {
changes[i].mark = m.Next()
m.changes = append(m.changes, markedChange{
mark: changes[i].mark,
state: changes[i].State,
})
}
}
}
// Import loads a marks file analogous to those used by git fast-export's
// --import-marks and --export-marks switches.
func (m *Marks) Import(filename string) error {
f, err := os.Open(filename)
if err != nil {
return err
}
defer f.Close()
br := bufio.NewReader(f)
for {
var mc markedChange
n, err := fmt.Fscanf(br, ":%d %s\n", &mc.mark, &mc.state)
if err == io.ErrUnexpectedEOF && n == 0 {
return nil
}
if err != nil {
return err
}
m.changes = append(m.changes, mc)
}
}
func (m *Marks) Export(filename string) error {
f, err := os.Create(filename)
if err != nil {
return err
}
for _, c := range m.changes {
fmt.Fprintf(f, ":%d %s\n", c.mark, c.state)
}
return f.Close()
}