summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@lukeshu.com>2017-11-15 16:19:23 -0500
committerLuke Shumaker <lukeshu@lukeshu.com>2017-11-15 16:19:23 -0500
commit29c005aded55168631029f9b129ff812ff96f802 (patch)
tree466eed0750d8976110e62e947c6ef6102dd450bb
parent902bb1cc2a0a8644e160f303be1a2e0ad354bfd5 (diff)
more
-rw-r--r--commands.go32
-rw-r--r--f.txt13
-rw-r--r--fileactions.go66
-rw-r--r--filter.go103
-rw-r--r--git-fast-import.go127
-rw-r--r--io.go16
-rw-r--r--read.go18
-rw-r--r--types.go2
-rw-r--r--util.go28
9 files changed, 127 insertions, 278 deletions
diff --git a/commands.go b/commands.go
index 6c5a0c7..a1f7f51 100644
--- a/commands.go
+++ b/commands.go
@@ -4,32 +4,8 @@ import (
"strconv"
)
-type ezfiw struct {
- fiw *FIWriter
- err error
-}
-
-func (e *ezfiw) WriteLine(a ...interface{}) {
- if e.err == nil {
- e.err = e.fiw.WriteLine(a...)
- }
-}
-
-func (e *ezfiw) WriteData(data []byte) {
- if e.err == nil {
- e.err = e.fiw.WriteData(data)
- }
-}
-
-func (e *ezfiw) WriteMark(idnum int) {
- if e.err == nil {
- e.err = e.fiw.WriteLine("mark", ":"+strconv.Itoa(idnum))
- }
-}
-
type Cmd interface {
fiWriteCmd(*FIWriter) error
- fiReadCmd(*FIReader) error
}
type CmdCommit struct {
@@ -53,7 +29,7 @@ func (c *CmdCommit) fiWriteCmd(fiw *FIWriter) error {
ez.WriteLine("author", *c.Author)
}
ez.WriteLine("committer", c.Committer)
- ez.WriteData(c.Data)
+ ez.WriteData(c.Msg)
if len(c.Parents) > 0 {
ez.WriteLine("from", c.Parents[0])
if len(c.Parents) > 1 {
@@ -68,7 +44,7 @@ func (c *CmdCommit) fiWriteCmd(fiw *FIWriter) error {
}
for _, action := range c.Tree {
- err := action.fiWriteFA(fi)
+ err := action.fiWriteFA(fiw)
if err != nil {
return err
}
@@ -120,7 +96,7 @@ func (c *CmdBlob) fiWriteCmd(fiw *FIWriter) error {
ez := &ezfiw{fiw: fiw}
ez.WriteLine("blob")
- if mark > 0 {
+ if c.Mark > 0 {
ez.WriteMark(c.Mark)
}
ez.WriteData(c.Data)
@@ -146,7 +122,7 @@ type CmdGetMark struct {
Mark int
}
-func (c *CmdGetmark) fiWriteCmd(fiw *FIWriter) error {
+func (c *CmdGetMark) fiWriteCmd(fiw *FIWriter) error {
return fiw.WriteLine("get-mark", ":"+strconv.Itoa(c.Mark))
}
diff --git a/f.txt b/f.txt
deleted file mode 100644
index 14dcb23..0000000
--- a/f.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-commit
-tag
-reset
-blob
-checkpoint
-progress
-feature
-option
-done
-#
-get-mark
-cat-blob
-ls
diff --git a/fileactions.go b/fileactions.go
index b45f776..2d81177 100644
--- a/fileactions.go
+++ b/fileactions.go
@@ -1,43 +1,47 @@
+package libfastimport
+
type FileAction interface {
- fiWrite(fi *FastImport) error
+ fiWriteFA(*FIWriter) error
}
type FileModify struct {
- Mode FileMode
- Path string
+ Mode Mode
+ Path Path
DataRef string
}
-func (o FileModify) fiWrite(fi *FastImport) error {
- return fi.printf(w, "M %06o %s %s\n", o.Mode, o.DataRef, pathEscape(o.Path))
+func (o FileModify) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("M", o.Mode, o.DataRef, o.Path)
}
type FileModifyInline struct {
- Mode FileMode
- Path string
+ Mode Mode
+ Path Path
Data []byte
}
-func (o FileModifyInline) fiWrite(fi *FastImport) error {
- fi.printf("M %06o inline %s\n", o.Mode, pathEscape(o.Path))
- return fi.data(o.Data)
+func (o FileModifyInline) fiWriteFA(fiw *FIWriter) error {
+ ez := &ezfiw{fiw: fiw}
+ ez.WriteLine("M", o.Mode, "inline", o.Path)
+ ez.WriteData(o.Data)
+ return ez.err
}
type FileDelete struct {
- Path string
+ Path Path
}
-func (o FileDelete) fiWrite(fi *FastImport) error {
- return fi.printf("D %s\n", pathEscape(o.Path))
+func (o FileDelete) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("D", o.Path)
}
type FileCopy struct {
- Src string
- Dst string
+ Src Path
+ Dst Path
}
-func (o FileCopy) fiWrite(fi *FastImport) error {
- return fi.printf("C %s %s\n", pathEscape(o.Src), pathEscape(o.Dst))
+func (o FileCopy) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("C", o.Src, o.Dst)
}
type FileRename struct {
@@ -45,14 +49,14 @@ type FileRename struct {
Dst string
}
-func (o FileRename) fiWrite(fi *FastImport) error {
- return fi.printf("R %s %s\n", pathEscape(o.Src), pathEscape(o.Dst))
+func (o FileRename) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("R", o.Src, o.Dst)
}
type FileDeleteAll struct{}
-func (o FileDeleteAll) fiWrite(fi *FastImport) error {
- return fi.printf("deleteall\n")
+func (o FileDeleteAll) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("deleteall")
}
type NoteModify struct {
@@ -60,8 +64,8 @@ type NoteModify struct {
DataRef string
}
-func (o NoteModify) fiWrite(fi *FastImport) error {
- return fi.printf("N %s %s\n", o.DataRef, o.CommitIsh)
+func (o NoteModify) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("N", o.DataRef, o.CommitIsh)
}
type NoteModifyInline struct {
@@ -69,8 +73,18 @@ type NoteModifyInline struct {
Data []byte
}
-func (o NoteModify) fiWrite(fi *FastImport) error {
- fi.printf("N inline %s\n", o.CommitIsh)
- return fi.data(o.Data)
+func (o NoteModifyInline) fiWriteFA(fiw *FIWriter) error {
+ ez := &ezfiw{fiw: fiw}
+ ez.WriteLine("N", "inline", o.CommitIsh)
+ ez.WriteData(o.Data)
+ return ez.err
}
+// See CmdLs for using ls outside of a commit
+type FileLs struct {
+ Path Path
+}
+
+func (o FileLs) fiWriteFA(fiw *FIWriter) error {
+ return fiw.WriteLine("ls", o.Path)
+}
diff --git a/filter.go b/filter.go
deleted file mode 100644
index 0c09963..0000000
--- a/filter.go
+++ /dev/null
@@ -1,103 +0,0 @@
-package main
-
-import (
- "os"
- "os/exec"
- "bytes"
-)
-
-var prog [string]string
-
-func init() {
- var err error
- for _, p := range []string{"git", "makepkg"} {
- prog[p], err = exec.LookPath("git")
- if err != nil {
- panic(err)
- }
- }
-}
-
-func pipeline(cmds ...*exec.Cmd) err error {
- for i, cmd := range cmds[:len(cmds)-1] {
- cmds[i+1].Stdin, err = cmd.StdoutPipe()
- if err != nil {
- return
- }
- }
-
- stderr := make([]bytes.Buffer, len(cmds))
- for i, cmd := range cmds {
- cmd.Stderr = &stderr[i]
- if err = cmd.Start(); err != nil {
- break
- }
- }
-
- for i, cmd := range cmds {
- if cmd.Process == nil {
- continue
- }
- if _err := cmd.Wait(); _err != nil {
- if ee, ok := _err.(*exec.ExitError); ok {
- ee.Stderr = stderr[i].Bytes()
- }
- if err != nil {
- err = _err
- }
- }
- }
- return
-}
-
-func pkgbuild2srcinfo(pkgbuildId string) (string, error) {
- cachefilename := "filter/pkgbuild2srcinfo/"+pkgbuildId
- for {
- b, err := ioutil.ReadFile(cachefilename)
- if err == nil && len(bytes.TrimSpace(b)) == 40 {
- return bytes.TrimSpace(b).String(), nil
- }
-
- file, err := os.OpenFile("filter/tmp/PKGBUILD", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- if err != nil {
- return "", err
- }
- err = pipeline(
- &exec.Cmd{
- Path: prog["git"], Args: ["git", "cat-file", "blob", pkgbuildId],
- Stdout: file,
- })
- file.Close()
- if err != nil {
- return "", err
- }
-
-
- file, err = os.OpenFile(cachefilename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
- err = pipeline(
- &exec.Cmd{
- Path: prog["makepkg"], Args: ["makepkg", "--printsrcinfo"],
- Dir: "filter/tmp"
- },
- &exec.Cmd{
- Path: prog["git"], Args: ["git", "hash-object", "-t", "blob", "-w", "--stdin", "--no-filters"],
- Stdout: &buf,
- })
- file.Close()
- if err != nil {
- return "", err
- }
- }
-}
-
-
-
-func filter(fromPfix string, toPfix string) {
- exec.Cmd{
- Path: prog["git"], Args: ["git", "fast-export",
- "--use-done-feature",
- "--no-data",
- "--", fromPfix + "/master"],
- }
-
-}
diff --git a/git-fast-import.go b/git-fast-import.go
index d9c7795..ed5cb14 100644
--- a/git-fast-import.go
+++ b/git-fast-import.go
@@ -1,118 +1,69 @@
package libfastimport
import (
- "time"
+ "fmt"
+ "bytes"
+ "strconv"
)
-type FastImport struct {
- w *FIWriter
- r *CatBlobReader
- err error
-}
-
-func (fi *FastImport) GetMark(mark int) (string, error) {
- if fi.printf("get-mark :%d\n", mark) != nil {
- return "", fi.ioErr
- }
- var dat [41]byte
- var n int
- _, fi.ioErr = io.ReadFull(fi.r, dat[:])
- if fi.ioErr != nil {
- return "", fi.ioErr
+func CatBlobParseGetMark(dat []byte) (string, error) {
+ if len(dat) != 41 {
+ return "", fmt.Errorf("get-mark: short <sha1>\\n: %q", string(dat))
}
if dat[40] != '\n' {
- fi.ioErr = fmt.Errorf("get-mark: malformed <sha1>\\n: %q", string(dat))
- return "", fi.ioErr
+ return "", fmt.Errorf("get-mark: malformed <sha1>\\n: %q", string(dat))
}
for _, b := range dat[:40] {
if !(('0' <= b && b <= '9') || ('a' <= b && b <= 'f')) {
- fi.ioErr = fmt.Errorf("get-mark: malformed <sha1>: %q", string(dat[:40]))
- return "", fi.ioErr
+ return "", fmt.Errorf("get-mark: malformed <sha1>: %q", string(dat[:40]))
}
}
- return string(dat[:40])
+ return string(dat[:40]), nil
}
-func (fi *FastImport) CatBlob(dataref string) (sha1 string, data []byte, err error) {
- if fi.println("cat-blob %s\n", dataref) != nil {
- return "", nil, fi.ioErr
- }
- // <sha1> SP 'blob' SP <size> LF
+func CatBlobParseCatBlob(full []byte) (sha1 string, data []byte, err error) {
+ // The format is:
//
- // That comes out to be 47+len(itoa(size)). Assuming that
- // size is at most a 64-bit integer (a safe assumption), then
- // its limit is 20 digits.
- var head [67]byte
- i := 0
- for {
- _, fi.ioErr = io.ReadFull(fi.r, head[i:i+1])
- if fi.ioErr != nil {
- return "", nil, fi.ioErr
- }
- if head[i] == '\n' {
- break
- }
- i++
- if i == len(head) {
- fi.ioErr = fmt.Errorf("cat-blob: overly-long header line: %q", string(head))
- return "", nil, fi.ioErr
- }
+ // <sha1> SP 'blob' SP <size> LF
+ // <data> LF
+
+ lf := bytes.IndexByte(full, '\n')
+ if lf < 0 || lf == len(full)-1 {
+ return "", nil, fmt.Errorf("cat-blob: malformed header: %q", string(full))
}
- i--
- if head[i] != '\n' {
- panic("wut")
+ head := full[:lf]
+ data = full[lf+1:len(full)-1]
+
+ if len(head) < 40+6+1 {
+ return "", nil, fmt.Errorf("cat-blob: malformed header: %q", string(head))
}
- for _, b := range head[:40] {
+
+ sha1 = string(head[:40])
+ for _, b := range sha1 {
if !(('0' <= b && b <= '9') || ('a' <= b && b <= 'f')) {
- fi.ioErr = fmt.Errorf("cat-blob: malformed <sha1>: %q", string(head[:40]))
- return "", nil, fi.ioErr
+ return "", nil, fmt.Errorf("cat-blob: malformed <sha1>: %q", sha1)
}
}
+
if string(head[40:46]) != " blob " {
- fi.ioErr = fmt.Errorf("cat-blob: malformed header: %q", string(head[:i]))
- return "", nil, fi.ioErr
+ return "", nil, fmt.Errorf("cat-blob: malformed header: %q", head)
}
- size, err := strconv.Atoi(string(head[46:i]))
+
+ size, err := strconv.Atoi(string(head[46:]))
if err != nil {
- fi.ioErr = fmt.Errorf("cat-blob: malformed blob size: %v", err)
- return "", nil, fi.ioErr
- }
- dat := make([]byte, size+1)
- _, fi.ioErr = io.ReadFull(fi.r, dat)
- if dat[size] != '\n' {
- fi.ioErr = fmt.Errorf("cat-blob: expected newline after data")
- return "", nil, fi.ioErr
+ return "", nil, fmt.Errorf("cat-blob: malformed blob size: %v", err)
}
- return string(head[:40]), dat[:size], nil
-}
-func (fi *FastImport) Ls(dataref string, path string) error {
- if dataref == "" {
- fi.printf("ls %s\n", quotePath(path))
- } else {
- fi.printf("ls %s %s\n", dataref, quotePath(path))
- }
- if fi.ioErr != nil {
- return fi.ioErr
+ if size != len(data) {
+ return "", nil, fmt.Errorf("cat-blob: size header (%d) didn't match delivered size (%d)", size, len(data))
}
- k
-}
-func (fi *FastImport) Feature() error
-func (fi *FastImport) Option() error
-func (fi *FastImport) Done() error {
- fi.printf("done\n")
- if fi.ioErr == nil {
- fi.ioErr = w.Close()
- }
- return fi.ioErr
+ return sha1, data, err
}
-func init() {
- x := exec.Cmd{
- Path: prog["git"],
- Args: {"git", "fast-import",
- "--done",
- "--cat-blob-fd=" + strconv.Itoa(TODO)},
- }
+func CatBlobParseLs(dataref string, path string) error {
+ // <mode> SP ('blob' | 'tree' | 'commit') SP <dataref> HT <path> LF
+ // or
+ // 'missing' SP <path> LF
+ return nil // TODO
}
diff --git a/io.go b/io.go
index f3f4909..f977b73 100644
--- a/io.go
+++ b/io.go
@@ -1,6 +1,7 @@
package libfastimport
import (
+ "fmt"
"bufio"
"bytes"
"io"
@@ -39,7 +40,7 @@ retry:
for !bytes.HasSuffix(line, suffix) {
_line, err = fir.r.ReadSlice('\n')
- line == append(line, _line)
+ line = append(line, _line...)
if err != nil {
return
}
@@ -53,7 +54,8 @@ retry:
}
_line := make([]byte, size+len(line))
copy(_line, line)
- n, err := io.ReadFull(fir.r, _line[len(line):])
+ var n int
+ n, err = io.ReadFull(fir.r, _line[len(line):])
line = _line[:n+len(line)]
}
}
@@ -70,12 +72,12 @@ func NewFIWriter(w io.Writer) *FIWriter {
}
}
-func (fiw *FIReader) WriteLine(a ...interface{}) error {
+func (fiw *FIWriter) WriteLine(a ...interface{}) error {
_, err := fmt.Fprintln(fiw.w, a...)
return err
}
-func (fiw *FIReader) WriteData(data []byte) error {
+func (fiw *FIWriter) WriteData(data []byte) error {
err := fiw.WriteLine("data", len(data))
if err != nil {
return err
@@ -96,7 +98,7 @@ func NewCatBlobReader(r io.Reader) *CatBlobReader {
func (cbr *CatBlobReader) ReadSlice() (line []byte, err error) {
retry:
- line, err = fir.r.ReadSlice('\n')
+ line, err = cbr.r.ReadSlice('\n')
if err != nil {
return
}
@@ -124,9 +126,9 @@ retry:
if err != nil {
return
}
- _line = make([]byte, len(line)+size+1)
+ _line := make([]byte, len(line)+size+1)
copy(_line, line)
- n, err := io.ReadFull(fir.r, _line[len(line):])
+ n, err := io.ReadFull(cbr.r, _line[len(line):])
line = _line[:n+len(line)]
return
}
diff --git a/read.go b/read.go
index cfe35c4..ea10885 100644
--- a/read.go
+++ b/read.go
@@ -23,33 +23,26 @@ func (p *Parser) GetCmd() (Cmd, error) {
return nil, err
}
}
- return p.cmd, nil
+ return <-p.cmd, nil
}
func (p *Parser) putSlice(slice []byte) error {
-}
-
-func utSlice(fir *FIReader) (Cmd, error) {
- slice, err := fir.PeekSlice()
- if err != nil {
- return nil, err
- }
if len(slice) < 1 {
- return nil, UnsupportedCommand(slice)
+ return UnsupportedCommand(slice)
}
switch slice[0] {
case '#': // comment
case 'b': // blob
case 'c':
if len(slice) < 2 {
- return nil, UnsupportedCommand(slice)
+ return UnsupportedCommand(slice)
}
switch slice[1] {
case 'o': // commit
case 'h': // checkpoint
case 'a': // cat-blob
default:
- return nil, UnsupportedCommand(slice)
+ return UnsupportedCommand(slice)
}
case 'd': // done
case 'f': // feature
@@ -60,6 +53,7 @@ func utSlice(fir *FIReader) (Cmd, error) {
case 'r': // reset
case 't': // tag
default:
- return nil, UnsupportedCommand(slice)
+ return UnsupportedCommand(slice)
}
+ return nil // TODO
}
diff --git a/types.go b/types.go
index d5c3f7a..1ce0741 100644
--- a/types.go
+++ b/types.go
@@ -43,7 +43,7 @@ func (m Mode) String() string {
}
func PathEscape(path string) string {
- if strings.HasPrefix(path, "\"") || strings.ContainsRune("\n") {
+ if strings.HasPrefix(path, "\"") || strings.ContainsRune(path, '\n') {
return "\"" + strings.Replace(strings.Replace(strings.Replace(path, "\\", "\\\\", -1), "\"", "\\\"", -1), "\n", "\\n", -1) + "\""
} else {
return path
diff --git a/util.go b/util.go
new file mode 100644
index 0000000..0143f48
--- /dev/null
+++ b/util.go
@@ -0,0 +1,28 @@
+package libfastimport
+
+import (
+ "strconv"
+)
+
+type ezfiw struct {
+ fiw *FIWriter
+ err error
+}
+
+func (e *ezfiw) WriteLine(a ...interface{}) {
+ if e.err == nil {
+ e.err = e.fiw.WriteLine(a...)
+ }
+}
+
+func (e *ezfiw) WriteData(data []byte) {
+ if e.err == nil {
+ e.err = e.fiw.WriteData(data)
+ }
+}
+
+func (e *ezfiw) WriteMark(idnum int) {
+ if e.err == nil {
+ e.err = e.fiw.WriteLine("mark", ":"+strconv.Itoa(idnum))
+ }
+}