Skip to content

Commit 127a5a1

Browse files
authored
Merge pull request #126 from netlify/get_original_size
Read original size from lfs pointers.
2 parents 59561d0 + d68c1f6 commit 127a5a1

File tree

7 files changed

+160
-39
lines changed

7 files changed

+160
-39
lines changed

Makefile

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
.PHONY: all build deps generate help test validate
22
CHECK_FILES?=$$(go list ./... | grep -v /vendor/)
33

4-
5-
6-
74
help: ## Show this help.
85
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
96

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ It's still a work in progress and we welcome feedback and contributions.
88

99
## Usage
1010

11-
The [`swagger.yml`](swagger.yml) file is the master copy of the Open API 2.0 definition. Additional context on using the API can be found on our [docs site](https://www.netlify.com/docs/api/).
11+
The [`swagger.yml`](swagger.yml) file is the master copy of the Open API 2.0 definition. Additional context on using the API can be found on our [docs site](https://www.netlify.com/docs/api/).
1212

1313
The spec is published and versioned for various ecosystems:
1414

go/plumbing/operations/upload_deploy_file_parameters.go

+30
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/plumbing/operations/upload_deploy_function_parameters.go

+31-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go/porcelain/deploy.go

+63-18
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 int64
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 *int64 `json:"size,omitempty"`
8995

9096
// Path OR Buffer should be populated
9197
Path string
@@ -410,6 +416,9 @@ func (n *Netlify) uploadFile(ctx context.Context, d *models.Deploy, f *FileBundl
410416
if operationError == nil {
411417
defer body.Close()
412418
params := operations.NewUploadDeployFileParams().WithDeployID(d.ID).WithPath(f.Name).WithFileBody(body)
419+
if f.Size != nil {
420+
params.WithSize(f.Size)
421+
}
413422
if timeout != 0 {
414423
params.SetTimeout(timeout)
415424
}
@@ -500,9 +509,19 @@ func walk(dir string, observer DeployObserver, useLargeMedia bool) (*deployFiles
500509
return err
501510
}
502511
defer o.Close()
503-
originalSha := getLFSSha(o)
504-
if originalSha != "" {
505-
file.Sum += ":" + string(originalSha)
512+
513+
data, err := readLFSData(o)
514+
if err != nil {
515+
return err
516+
}
517+
518+
if data != nil {
519+
if data.SHA != "" {
520+
file.Sum += ":" + data.SHA
521+
}
522+
if data.Size > 0 {
523+
file.Size = &data.Size
524+
}
506525
}
507526
}
508527

@@ -654,18 +673,44 @@ func createHeader(archive *zip.Writer, i os.FileInfo, runtime string) (io.Writer
654673
return archive.Create(i.Name())
655674
}
656675

657-
func getLFSSha(file io.Reader) string {
676+
func readLFSData(file io.Reader) (*pointerData, error) {
658677
// currently this only supports certain type of git lfs pointer files
659678
// 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-
}
679+
data := make([]byte, len(lfsVersionString))
680+
count, err := file.Read(data)
681+
if err != nil {
682+
// ignore file if it's not an LFS pointer with the expected header
683+
return nil, nil
684+
}
685+
if count != len(lfsVersionString) || string(data) != lfsVersionString {
686+
// ignore file if it's not an LFS pointer with the expected header
687+
return nil, nil
688+
}
689+
690+
scanner := bufio.NewScanner(file)
691+
values := map[string]string{}
692+
for scanner.Scan() {
693+
keyAndValue := bytes.SplitN(scanner.Bytes(), []byte(" "), 2)
694+
if len(keyAndValue) > 1 {
695+
values[string(keyAndValue[0])] = string(keyAndValue[1])
668696
}
669697
}
670-
return ""
698+
699+
var sha string
700+
oid, ok := values["oid"]
701+
if !ok {
702+
return nil, fmt.Errorf("missing LFS OID")
703+
}
704+
705+
sha = strings.SplitN(oid, ":", 2)[1]
706+
707+
size, err := strconv.ParseInt(values["size"], 10, 0)
708+
if err != nil {
709+
return nil, err
710+
}
711+
712+
return &pointerData{
713+
SHA: sha,
714+
Size: size,
715+
}, nil
671716
}

go/porcelain/deploy_test.go

+29-15
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) {

swagger.yml

+6
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,9 @@ paths:
757757
type: string
758758
in: path
759759
required: true
760+
- name: size
761+
type: integer
762+
in: query
760763
- name: file_body
761764
in: body
762765
schema:
@@ -787,6 +790,9 @@ paths:
787790
- name: runtime
788791
type: string
789792
in: query
793+
- name: size
794+
type: integer
795+
in: query
790796
- name: file_body
791797
in: body
792798
schema:

0 commit comments

Comments
 (0)