2015-04-23 16:40:45 +00:00
|
|
|
package lfs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
)
|
|
|
|
|
2015-04-23 17:44:11 +00:00
|
|
|
// Uploadable describes a file that can be uploaded.
|
2015-04-23 16:40:45 +00:00
|
|
|
type Uploadable struct {
|
2015-05-21 16:36:49 +00:00
|
|
|
oid string
|
|
|
|
OidPath string
|
2015-04-23 16:40:45 +00:00
|
|
|
Filename string
|
2015-05-21 16:36:49 +00:00
|
|
|
size int64
|
2015-05-07 18:33:51 +00:00
|
|
|
object *objectResource
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-04-23 17:44:11 +00:00
|
|
|
// NewUploadable builds the Uploadable from the given information.
|
2015-07-06 11:05:34 +00:00
|
|
|
// "filename" can be empty if a raw object is pushed (see "object-id" flag in push command)/
|
2015-07-06 11:13:57 +00:00
|
|
|
func NewUploadable(oid, filename string) (*Uploadable, *WrappedError) {
|
2015-07-06 11:05:34 +00:00
|
|
|
localMediaPath, err := LocalMediaPath(oid)
|
2015-04-23 16:40:45 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, Errorf(err, "Error uploading file %s (%s)", filename, oid)
|
|
|
|
}
|
|
|
|
|
2015-07-06 11:05:34 +00:00
|
|
|
if len(filename) > 0 {
|
|
|
|
if err := ensureFile(filename, localMediaPath); err != nil {
|
|
|
|
return nil, Errorf(err, "Error uploading file %s (%s)", filename, oid)
|
|
|
|
}
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-07-06 17:29:13 +00:00
|
|
|
fi, err := os.Stat(localMediaPath)
|
2015-04-24 15:43:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, Errorf(err, "Error uploading file %s (%s)", filename, oid)
|
|
|
|
}
|
|
|
|
|
2015-07-06 11:05:34 +00:00
|
|
|
return &Uploadable{oid: oid, OidPath: localMediaPath, Filename: filename, size: fi.Size()}, nil
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) Check() (*objectResource, *WrappedError) {
|
|
|
|
return UploadCheck(u.OidPath)
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) Transfer(cb CopyCallback) *WrappedError {
|
|
|
|
wcb := func(total, read int64, current int) error {
|
|
|
|
cb(total, read, current)
|
|
|
|
return nil
|
2015-04-24 15:43:38 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
return UploadObject(u.object, wcb)
|
2015-05-07 18:33:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) Object() *objectResource {
|
|
|
|
return u.object
|
2015-05-07 18:33:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) Oid() string {
|
|
|
|
return u.oid
|
2015-04-24 15:43:38 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) Size() int64 {
|
|
|
|
return u.size
|
|
|
|
}
|
2015-04-24 15:43:38 +00:00
|
|
|
|
2015-06-19 17:59:30 +00:00
|
|
|
func (u *Uploadable) Name() string {
|
|
|
|
return u.Filename
|
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
func (u *Uploadable) SetObject(o *objectResource) {
|
|
|
|
u.object = o
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-05-21 16:36:49 +00:00
|
|
|
// NewUploadQueue builds an UploadQueue, allowing `workers` concurrent uploads.
|
|
|
|
func NewUploadQueue(workers, files int) *TransferQueue {
|
2015-07-09 18:21:49 +00:00
|
|
|
q := newTransferQueue(workers)
|
2015-05-21 16:36:49 +00:00
|
|
|
q.transferKind = "upload"
|
|
|
|
return q
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ensureFile makes sure that the cleanPath exists before pushing it. If it
|
|
|
|
// does not exist, it attempts to clean it by reading the file at smudgePath.
|
|
|
|
func ensureFile(smudgePath, cleanPath string) error {
|
|
|
|
if _, err := os.Stat(cleanPath); err == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
expectedOid := filepath.Base(cleanPath)
|
|
|
|
localPath := filepath.Join(LocalWorkingDir, smudgePath)
|
|
|
|
file, err := os.Open(localPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
defer file.Close()
|
|
|
|
|
|
|
|
stat, err := file.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
cleaned, err := PointerClean(file, stat.Size(), nil)
|
2015-07-06 16:50:16 +00:00
|
|
|
if cleaned != nil {
|
|
|
|
cleaned.Teardown()
|
2015-04-23 16:40:45 +00:00
|
|
|
}
|
|
|
|
|
2015-07-06 16:50:16 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2015-06-27 15:36:10 +00:00
|
|
|
}
|
2015-04-23 16:40:45 +00:00
|
|
|
|
|
|
|
if expectedOid != cleaned.Oid {
|
|
|
|
return fmt.Errorf("Expected %s to have an OID of %s, got %s", smudgePath, expectedOid, cleaned.Oid)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|