PackageManager just because
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

214 lines
3.1 KiB

package Filesystem
import (
"bytes"
"crypto/sha1"
"encoding/gob"
"encoding/hex"
"errors"
"fmt"
"hash"
"io"
"os"
"path/filepath"
)
var (
// TODO: Where do I put this
Data string
)
type Package struct {
Name string
Version string
}
type FileObject struct {
FileMode os.FileMode
Size int64
Package Package
Ref string
Sha1 []byte
}
type ByName []Package
func (f FileObject) IsLink() bool {
return f.FileMode&os.ModeSymlink != 0
}
func (f FileObject) objFile() string {
return filepath.Join(f.objDir(), hex.EncodeToString(f.Sha1))
}
func (f FileObject) objDir() string {
return filepath.Join(Data, hex.EncodeToString(f.Sha1[:2]))
}
func (f FileObject) Reset(dst string) error {
var err error
if f.IsLink() {
_, err = os.Lstat(dst)
if !os.IsNotExist(err) {
err = os.Remove(dst)
if err != nil {
return err
}
}
err = os.Symlink(f.Ref, dst)
if err != nil {
return err
}
return nil
}
f.cp(f.objFile(), dst)
err = os.Chmod(dst, f.FileMode)
if err != nil {
return err
}
return nil
}
func (f FileObject) Stov(src string) error {
var err error
if f.IsLink() {
return nil
}
err = os.MkdirAll(f.objDir(), 0744)
if err != nil {
return err
}
f.cp(src, f.objFile())
return nil
}
func (f FileObject) cp(src string, dst string) error {
var (
srcFile, dstFile *os.File
err error
)
fmt.Println("cp ", src, dst)
srcFile, err = os.Open(src)
if err != nil {
return err
}
defer srcFile.Close()
dstFile, err = os.Create(dst)
if err != nil {
return err
}
defer dstFile.Close()
_, err = io.Copy(dstFile, srcFile)
if err != nil {
return err
}
return dstFile.Sync()
}
func (f FileObject) IsDifferent(fn FileObject) error {
if f.FileMode != fn.FileMode {
return errors.New("mode does not match")
}
if f.IsLink() {
if f.Ref != fn.Ref {
return errors.New("ref does not match")
}
return nil
}
if f.Size != fn.Size {
return errors.New("size does not match")
}
if !bytes.Equal(f.Sha1, fn.Sha1) {
return errors.New("sha1 does not match")
}
return nil
}
func CreateFileObject(f string) (FileObject, error) {
var (
sha1Hash hash.Hash = sha1.New()
fo FileObject
fi os.FileInfo
file *os.File
err error
)
fi, err = os.Lstat(f)
if err != nil {
return fo, err
}
fo = FileObject{
FileMode: fi.Mode(),
Size: fi.Size(),
}
if fo.IsLink() {
fo.Ref, err = os.Readlink(f)
if err != nil {
return fo, err
}
return fo, nil
}
file, err = os.Open(f)
if err != nil {
return fo, err
}
defer file.Close()
io.Copy(sha1Hash, file)
fo.Sha1 = sha1Hash.Sum(nil)
return fo, nil
}
func (f FileObject) ToBytes() ([]byte, error) {
var (
encoder *gob.Encoder
buf bytes.Buffer
err error
)
encoder = gob.NewEncoder(&buf)
err = encoder.Encode(f)
return buf.Bytes(), err
}
func FromBytes(v []byte) (FileObject, error) {
var (
buf *bytes.Buffer
decoder *gob.Decoder
fo FileObject
err error
)
buf = bytes.NewBuffer(v)
decoder = gob.NewDecoder(buf)
err = decoder.Decode(&fo)
if err != nil {
return fo, err
}
return fo, nil
}