Permalink
Browse files

Refactor parseObj to use io.Reader interface instead of ioutil

  • Loading branch information...
1 parent 6ef75c0 commit 2e3a6c1bf6cbe5ddefe5531b8b34d2c9b3a10ac3 @ChimeraCoder committed May 13, 2015
Showing with 62 additions and 20 deletions.
  1. +62 −20 object.go
View
@@ -15,6 +15,43 @@ import (
"time"
)
+type scanner struct {
+ r io.Reader
+ data []byte
+ err error
+}
+
+func (s *scanner) scan() bool {
+ if s.err != nil {
+ return false
+ }
+ s.data = s.read()
+ return s.err == nil
+}
+
+func (s *scanner) Err() error {
+ if s.err == io.EOF {
+ return nil
+ }
+ return s.err
+}
+
+func (s *scanner) read() []byte {
+ if s.err != nil {
+ return nil
+ }
+ result := make([]byte, 1)
+ n, err := s.r.Read(result)
+ if err != nil {
+ s.err = err
+ return nil
+ }
+ if n == 0 {
+ s.err = fmt.Errorf("read zero bytes")
+ }
+ return result
+}
+
const (
RFC2822 = "Mon Jan 2 15:04:05 2006 -0700"
)
@@ -206,27 +243,37 @@ func normalizePerms(perms string) string {
}
func parseObj(r io.Reader, name SHA, basedir string) (result GitObject, err error) {
- // TODO fixme
- bts, err := ioutil.ReadAll(r)
- if err != nil {
- return result, err
+
+ var resultType string
+ var resultSize string
+ scnr := scanner{r, nil, nil}
+ for scnr.scan() {
+ txt := string(scnr.data)
+ if txt == " " {
+ break
+ }
+ resultType += txt
}
- obj := bts
- parts := bytes.Split(obj, []byte("\x00"))
- parts = bytes.Fields(parts[0])
- resultType := string(parts[0])
- resultSize := string(parts[1])
- nullIndex := bytes.Index(obj, []byte("\x00"))
+ for scnr.scan() {
+ txt := string(scnr.data)
+ if txt == "\x00" {
+ break
+ }
+ resultSize += txt
+ }
+
+ if scnr.Err() != nil {
+ return nil, scnr.Err()
+ }
switch resultType {
case "commit":
- return parseCommit(bytes.NewReader(obj[nullIndex+1:]), resultSize, name)
+ return parseCommit(r, resultSize, name)
case "tree":
- return parseTree(bytes.NewReader(obj), resultSize, basedir)
-
+ return parseTree(r, resultSize, basedir)
case "blob":
- return parseBlob(bytes.NewReader(obj[nullIndex+1:]), resultSize)
+ return parseBlob(r, resultSize)
default:
err = fmt.Errorf("Received unknown object type %s", resultType)
}
@@ -317,11 +364,6 @@ func parseTree(r io.Reader, resultSize string, basedir string) (Tree, error) {
if count == 0 {
// the first time through, scanner.Text() will be
- // "tree <size>"
- continue
- }
- if count == 1 {
- // the second time through, scanner.Text() will be
// <perms> <filename>
// separated by a space
fields := strings.Fields(txt)
@@ -330,7 +372,7 @@ func parseTree(r io.Reader, resultSize string, basedir string) (Tree, error) {
continue
}
- // after the second time through, scanner.Text() will be
+ // after the first time through, scanner.Text() will be
// <sha><perms2> <file2>
// where perms2 and file2 refer to the permissions and filename (respectively)
// of the NEXT object, and <sha> is the first 20 bytes exactly.

0 comments on commit 2e3a6c1

Please sign in to comment.