Skip to content

Commit f27b426

Browse files
committed
Read original size from lfs pointers.
So we can store that information. Signed-off-by: David Calavera <[email protected]>
1 parent 59561d0 commit f27b426

File tree

2 files changed

+89
-33
lines changed

2 files changed

+89
-33
lines changed

go/porcelain/deploy.go

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package porcelain
22

33
import (
44
"archive/zip"
5+
"bufio"
56
"bytes"
67
"crypto/sha1"
78
"crypto/sha256"
@@ -12,7 +13,7 @@ import (
1213
"io/ioutil"
1314
"os"
1415
"path/filepath"
15-
"regexp"
16+
"strconv"
1617
"strings"
1718
"sync"
1819
"time"
@@ -33,15 +34,19 @@ const (
3334
goRuntime = "go"
3435

3536
preProcessingTimeout = time.Minute * 5
36-
)
37-
38-
type uploadType int
3937

40-
const (
4138
fileUpload uploadType = iota
4239
functionUpload
40+
41+
lfsVersionString = "version https://git-lfs.github.com/spec/v1"
4342
)
4443

44+
type uploadType int
45+
type pointerData struct {
46+
SHA string
47+
Size int
48+
}
49+
4550
type DeployObserver interface {
4651
OnSetupWalk() error
4752
OnSuccessfulStep(*FileBundle) error
@@ -86,6 +91,7 @@ type FileBundle struct {
8691
Name string
8792
Sum string
8893
Runtime string
94+
Size *int `json:"size,omitempty"`
8995

9096
// Path OR Buffer should be populated
9197
Path string
@@ -500,9 +506,19 @@ func walk(dir string, observer DeployObserver, useLargeMedia bool) (*deployFiles
500506
return err
501507
}
502508
defer o.Close()
503-
originalSha := getLFSSha(o)
504-
if originalSha != "" {
505-
file.Sum += ":" + string(originalSha)
509+
510+
data, err := readLFSData(o)
511+
if err != nil {
512+
return err
513+
}
514+
515+
if data != nil {
516+
if data.SHA != "" {
517+
file.Sum += ":" + data.SHA
518+
}
519+
if data.Size > 0 {
520+
file.Size = &data.Size
521+
}
506522
}
507523
}
508524

@@ -654,18 +670,44 @@ func createHeader(archive *zip.Writer, i os.FileInfo, runtime string) (io.Writer
654670
return archive.Create(i.Name())
655671
}
656672

657-
func getLFSSha(file io.Reader) string {
673+
func readLFSData(file io.Reader) (*pointerData, error) {
658674
// currently this only supports certain type of git lfs pointer files
659675
// version [version]\noid sha256:[oid]\nsize [size]
660-
data := make([]byte, 150)
661-
if count, err := file.Read(data); err == nil {
662-
r, _ := regexp.Compile(`^version \S+\noid sha256:(\S+)\n`)
663-
res := r.FindSubmatch(data[:count])
664-
if len(res) == 2 {
665-
if originalSha := res[1]; len(originalSha) == 64 {
666-
return string(originalSha)
667-
}
676+
data := make([]byte, len(lfsVersionString))
677+
count, err := file.Read(data)
678+
if err != nil {
679+
// ignore file if it's not an LFS pointer with the expected header
680+
return nil, nil
681+
}
682+
if count != len(lfsVersionString) {
683+
// ignore file if it's not an LFS pointer with the expected header
684+
return nil, nil
685+
}
686+
687+
scanner := bufio.NewScanner(file)
688+
values := map[string]string{}
689+
for scanner.Scan() {
690+
keyAndValue := bytes.SplitN(scanner.Bytes(), []byte(" "), 2)
691+
if len(keyAndValue) > 1 {
692+
values[string(keyAndValue[0])] = string(keyAndValue[1])
668693
}
669694
}
670-
return ""
695+
696+
var sha string
697+
oid, ok := values["oid"]
698+
if !ok {
699+
return nil, fmt.Errorf("missing LFS OID")
700+
}
701+
702+
sha = strings.SplitN(oid, ":", 2)[1]
703+
704+
size, err := strconv.Atoi(values["size"])
705+
if err != nil {
706+
return nil, err
707+
}
708+
709+
return &pointerData{
710+
SHA: sha,
711+
Size: size,
712+
}, nil
671713
}

go/porcelain/deploy_test.go

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,37 @@ import (
66
)
77

88
func TestGetLFSSha(t *testing.T) {
9-
tests := []struct {
10-
contents string
11-
length int
12-
}{
13-
{"Not a pointer file", 0},
14-
{"version https://git-lfs.github.com/spec/v1\n" +
15-
"oid sha256:7e56e498ccb4cbb9c672e1aed6710fb91b2fd314394a666c11c33b2059ea3d71\n" +
16-
"size 1743570", 64},
17-
}
9+
t.Run("test with not a pointer file", func(t *testing.T) {
10+
file := strings.NewReader("Not a pointer file")
11+
data, err := readLFSData(file)
12+
if err != nil {
13+
t.Fatal(err)
14+
}
1815

19-
for _, test := range tests {
20-
file := strings.NewReader(test.contents)
21-
out := getLFSSha(file)
22-
if len(out) != test.length {
23-
t.Fatalf("expected `%d`, got `%d`", test.length, len(out))
16+
if data != nil {
17+
t.Fatal("expected data to be nil without proper formatting")
2418
}
25-
}
19+
})
20+
21+
t.Run("test with v1 pointer", func(t *testing.T) {
22+
content := `version https://git-lfs.github.com/spec/v1
23+
oid sha256:7e56e498ccb4cbb9c672e1aed6710fb91b2fd314394a666c11c33b2059ea3d71
24+
size 1743570
25+
`
26+
file := strings.NewReader(content)
27+
data, err := readLFSData(file)
28+
if err != nil {
29+
t.Fatal(err)
30+
}
31+
32+
if data.SHA != "7e56e498ccb4cbb9c672e1aed6710fb91b2fd314394a666c11c33b2059ea3d71" {
33+
t.Fatalf("expected `7e56e498ccb4cbb9c672e1aed6710fb91b2fd314394a666c11c33b2059ea3d71`, got `%v`", data.SHA)
34+
}
35+
36+
if data.Size != 1743570 {
37+
t.Fatalf("expected `1743570`, got `%v`", data.Size)
38+
}
39+
})
2640
}
2741

2842
func TestAddWithLargeMedia(t *testing.T) {

0 commit comments

Comments
 (0)