diff --git a/commands/command_migrate_export.go b/commands/command_migrate_export.go index 3ba1f9be..d910c070 100644 --- a/commands/command_migrate_export.go +++ b/commands/command_migrate_export.go @@ -1,7 +1,6 @@ package commands import ( - "bytes" "fmt" "os" "path/filepath" @@ -45,15 +44,20 @@ func migrateExportCommand(cmd *cobra.Command, args []string) { return b, nil } - var buf bytes.Buffer - - if _, err := smudge(gitfilter, &buf, b.Contents, path, false, rewriter.Filter()); err != nil { + ptr, err := lfs.DecodePointer(b.Contents) + if errors.IsNotAPointerError(err) { + return b, nil + } + if err != nil { return nil, err } - return &odb.Blob{ - Contents: &buf, Size: int64(buf.Len()), - }, nil + downloadPath, err := gitfilter.ObjectPath(ptr.Oid) + if err != nil { + return nil, err + } + + return odb.NewBlobFromFile(downloadPath) }, TreeCallbackFn: func(path string, t *odb.Tree) (*odb.Tree, error) { diff --git a/git/odb/blob.go b/git/odb/blob.go index 7f9d66ae..0862b693 100644 --- a/git/odb/blob.go +++ b/git/odb/blob.go @@ -3,6 +3,9 @@ package odb import ( "bytes" "io" + "os" + + "github.com/git-lfs/git-lfs/errors" ) // Blob represents a Git object of type "blob". @@ -27,6 +30,42 @@ func NewBlobFromBytes(contents []byte) *Blob { } } +// NewBlobFromFile returns a new *Blob that contains the contents of the file +// at location "path" on disk. NewBlobFromFile does not read the file ahead of +// time, and instead defers this task until encoding the blob to the object +// database. +// +// If the file cannot be opened or stat(1)-ed, an error will be returned. +// +// When the blob receives a function call Close(), the file will also be closed, +// and any error encountered in doing so will be returned from Close(). +func NewBlobFromFile(path string) (*Blob, error) { + f, err := os.Open(path) + if err != nil { + return nil, errors.Wrapf(err, "git/odb: could not open: %s", + path) + } + + stat, err := f.Stat() + if err != nil { + return nil, errors.Wrapf(err, "git/odb: could not stat %s", + path) + } + + return &Blob{ + Contents: f, + Size: stat.Size(), + + closeFn: func() error { + if err := f.Close(); err != nil { + return errors.Wrapf(err, + "git/odb: could not close %s", path) + } + return nil + }, + }, nil +} + // Type implements Object.ObjectType by returning the correct object type for // Blobs, BlobObjectType. func (b *Blob) Type() ObjectType { return BlobObjectType }