commands: directly convert ptr to object

When performing an export, directly convert an LFS pointer to an
object using the downloaded object file, skipping over the smudge.

Thanks to @ttaylorr for the implementation of the
NewBlobFromFile() function
This commit is contained in:
Preben Ingvaldsen 2018-06-25 14:36:57 -07:00
parent 785200e85d
commit 3a07215cc3
2 changed files with 50 additions and 7 deletions

@ -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) {

@ -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 }