@@ -2,6 +2,7 @@ package porcelain
22
33import (
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+
4550type 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}
0 commit comments