From ce0f40c125ff838d332c1974c8e505e4be1e409b Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 16 Nov 2017 10:08:15 -0500 Subject: more --- backend.go | 70 ++++++++++++++++++++++++++++++ frontend.go | 123 +++++++++++++++++++++++++++++++++++------------------ read_fastimport.go | 63 --------------------------- textproto/io.go | 6 +++ 4 files changed, 157 insertions(+), 105 deletions(-) create mode 100644 backend.go delete mode 100644 read_fastimport.go diff --git a/backend.go b/backend.go new file mode 100644 index 0000000..4d03d46 --- /dev/null +++ b/backend.go @@ -0,0 +1,70 @@ +package libfastimport + +import ( + "io" + "bufio" + + "git.lukeshu.com/go/libfastimport/textproto" +) + +// A Backend is something that consumes a fast-import stream; the +// Backend object provides methods for writing to it. +type Backend struct { + w *bufio.Writer + fiw *textproto.FIWriter + cbr *textproto.CatBlobReader +} + +func NewBackend(fastImport io.Writer, catBlob io.Reader) *Backend { + ret := Backend{} + ret.w = bufio.NewWriter(fastImport) + ret.fiw = textproto.NewFIWriter(ret.w) + if catBlob != nil { + ret.cbr = textproto.NewCatBlobReader(catBlob) + } + return &ret +} + +func (b *Backend) Do(cmd Cmd) error { + err := cmd.fiWriteCmd(b.fiw) + if err != nil { + return err + } + return b.w.Flush() +} + +func (b *Backend) GetMark(cmd CmdGetMark) (string, error) { + err := b.Do(cmd) + if err != nil { + return "", err + } + line, err := b.cbr.ReadLine() + if err != nil { + return "", err + } + return cbpGetMark(line) +} + +func (b *Backend) CatBlob(cmd CmdCatBlob) (sha1 string, data string, err error) { + err = b.Do(cmd) + if err != nil { + return "", "", err + } + line, err := b.cbr.ReadLine() + if err != nil { + return "", "", err + } + return cbpCatBlob(line) +} + +func (b *Backend) Ls(cmd CmdLs) (mode textproto.Mode, dataref string, path textproto.Path, err error) { + err = b.Do(cmd) + if err != nil { + return 0, "", "", err + } + line, err := b.cbr.ReadLine() + if err != nil { + return 0, "", "", err + } + return cbpLs(line) +} diff --git a/frontend.go b/frontend.go index 73f6d73..405ead4 100644 --- a/frontend.go +++ b/frontend.go @@ -1,68 +1,107 @@ package libfastimport import ( - "io" "bufio" + "io" + "strings" "git.lukeshu.com/go/libfastimport/textproto" ) +type UnsupportedCommand string + +func (e UnsupportedCommand) Error() string { + return "Unsupported command: " + string(e) +} + +type cmderror struct { + Cmd + error +} + +// A Frontend is something that produces a fast-import stream; the +// Frontend object provides methods for reading from it. type Frontend struct { - w *bufio.Writer - fiw *textproto.FIWriter - cbr *textproto.CatBlobReader + fir *textproto.FIReader + cbw *textproto.CatBlobWriter + w *bufio.Writer + c chan cmderror } -func NewFrontend(w io.Writer, r io.Reader) *Frontend { +func NewFrontend(fastImport io.Reader, catBlob io.Writer) *Frontend { ret := Frontend{} - ret.w = bufio.NewWriter(w) - ret.fiw = textproto.NewFIWriter(ret.w) - if r != nil { - ret.cbr = textproto.NewCatBlobReader(r) + ret.fir = textproto.NewFIReader(fastImport) + if catBlob != nil { + ret.w = bufio.NewWriter(catBlob) + ret.cbw = textproto.NewCatBlobWriter(ret.w) } return &ret } -func (f *Frontend) Do(cmd Cmd) error { - err := cmd.fiWriteCmd(f.fiw) +func (f *Frontend) nextLine() (line string, err error) { +retry: + line, err = f.fir.ReadLine() if err != nil { - return err + return + } + switch { + case strings.HasPrefix(line, "#"): + f.c <- cmderror{CmdComment{Comment: line[1:]}, nil} + goto retry + case strings.HasPrefix(line, "cat-blob "): + f.c <- parse_cat_blob(line) + goto retry + case strings.HasPrefix(line, "get-mark "): + f.c <- parse_get_mark(line) + goto retry + default: + return } - return f.w.Flush() } -func (f *Frontend) GetMark(cmd CmdGetMark) (string, error) { - err := f.Do(cmd) - if err != nil { - return "", err +func (f *Frontend) parse() { + for { + line, err := f.nextLine() + if err != nil { + f.c <- cmderror{nil, err} + return + } + switch { + case strings.HasPrefix(line, "blob "): + case strings.HasPrefix(line, "commit "): + case strings.HasPrefix(line, "checkpoint\n"): + case strings.HasPrefix(line, "done\n"): + case strings.HasPrefix(line, "feature "): + case strings.HasPrefix(line, "ls "): + case strings.HasPrefix(line, "option "): + case strings.HasPrefix(line, "progress "): + case strings.HasPrefix(line, "reset "): + case strings.HasPrefix(line, "tag "): + default: + f.c <- cmderror{nil, UnsupportedCommand(line)} + return + } } - line, err := f.cbr.ReadLine() - if err != nil { - return "", err - } - return cbpGetMark(line) } -func (f *Frontend) CatBlob(cmd CmdCatBlob) (sha1 string, data string, err error) { - err = f.Do(cmd) - if err != nil { - return "", "", err - } - line, err := f.cbr.ReadLine() - if err != nil { - return "", "", err - } - return cbpCatBlob(line) +func (f *Frontend) ReadCmd() (Cmd, error) { + cmderror := <-f.c + cmd := cmderror.Cmd + err := cmderror.error + return cmderror.Cmd, cmderror.error } -func (f *Frontend) Ls(cmd CmdLs) (mode textproto.Mode, dataref string, path textproto.Path, err error) { - err = f.Do(cmd) - if err != nil { - return 0, "", "", err - } - line, err := f.cbr.ReadLine() - if err != nil { - return 0, "", "", err - } - return cbpLs(line) +func (f *Frontend) RespondGetMark(sha1 string) error { + // TODO + return f.w.Flush() +} + +func (f *Frontend) RespondCatBlob(sha1 string, data string) error { + // TODO + return f.w.Flush() +} + +func (f *Frontend) RespondLs(mode textproto.Mode, dataref string, path textproto.Path) error { + // TODO + return f.w.Flush() } diff --git a/read_fastimport.go b/read_fastimport.go deleted file mode 100644 index abafa4b..0000000 --- a/read_fastimport.go +++ /dev/null @@ -1,63 +0,0 @@ -package libfastimport - -import ( - "git.lukeshu.com/go/libfastimport/textproto" -) - -type UnsupportedCommand string - -func (e UnsupportedCommand) Error() string { - return "Unsupported command: "+string(e) -} - -type Parser struct { - fir *textproto.FIReader - - cmd chan Cmd -} - -func (p *Parser) GetCmd() (Cmd, error) { - for p.cmd == nil { - line, err := p.fir.ReadLine() - if err != nil { - return nil, err - } - err = p.putLine(line) - if err != nil { - return nil, err - } - } - return <-p.cmd, nil -} - -func (p *Parser) putLine(line string) error { - if len(line) < 1 { - return UnsupportedCommand(line) - } - switch line[0] { - case '#': // comment - case 'b': // blob - case 'c': - if len(line) < 2 { - return UnsupportedCommand(line) - } - switch line[1] { - case 'o': // commit - case 'h': // checkpoint - case 'a': // cat-blob - default: - return UnsupportedCommand(line) - } - case 'd': // done - case 'f': // feature - case 'g': // get-mark - case 'l': // ls - case 'o': // option - case 'p': // progress - case 'r': // reset - case 't': // tag - default: - return UnsupportedCommand(line) - } - return nil // TODO -} diff --git a/textproto/io.go b/textproto/io.go index af2cb19..cb0105b 100644 --- a/textproto/io.go +++ b/textproto/io.go @@ -131,6 +131,12 @@ type CatBlobWriter struct { w io.Writer } +func NewCatBlobWriter(w io.Writer) *CatBlobWriter { + return &CatBlobWriter { + w: w, + } +} + func (cbw *CatBlobWriter) WriteLine(a ...interface{}) error { _, err := fmt.Fprintln(cbw.w, a...) return err -- cgit v1.2.3