From 85a91266571a966f10e73bdd641d753eb0431a7a Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Mon, 19 Jun 2017 15:03:30 +0200 Subject: worktree: Add create and push the blob objects to the storer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Máximo Cuadros --- worktree_commit.go | 108 ++++++----------------------------------------------- worktree_status.go | 52 ++++++++++++++++---------- worktree_test.go | 11 ++++++ 3 files changed, 56 insertions(+), 115 deletions(-) diff --git a/worktree_commit.go b/worktree_commit.go index fc63d16..a342240 100644 --- a/worktree_commit.go +++ b/worktree_commit.go @@ -1,8 +1,6 @@ package git import ( - "io" - "os" "path/filepath" "strings" @@ -11,7 +9,6 @@ import ( "gopkg.in/src-d/go-git.v4/plumbing/format/index" "gopkg.in/src-d/go-git.v4/plumbing/object" "gopkg.in/src-d/go-git.v4/storage" - "gopkg.in/src-d/go-git.v4/utils/ioutil" "gopkg.in/src-d/go-billy.v3" ) @@ -34,12 +31,12 @@ func (w *Worktree) Commit(msg string, opts *CommitOptions) (plumbing.Hash, error return plumbing.ZeroHash, err } - h := &commitIndexHelper{ + h := &buildTreeHelper{ fs: w.fs, s: w.r.Storer, } - tree, err := h.buildTreeAndBlobObjects(idx) + tree, err := h.BuildTree(idx) if err != nil { return plumbing.ZeroHash, err } @@ -103,10 +100,10 @@ func (w *Worktree) buildCommitObject(msg string, opts *CommitOptions, tree plumb return w.r.Storer.SetEncodedObject(obj) } -// commitIndexHelper converts a given index.Index file into multiple git objects +// buildTreeHelper converts a given index.Index file into multiple git objects // reading the blobs from the given filesystem and creating the trees from the // index structure. The created objects are pushed to a given Storer. -type commitIndexHelper struct { +type buildTreeHelper struct { fs billy.Filesystem s storage.Storer @@ -114,9 +111,9 @@ type commitIndexHelper struct { entries map[string]*object.TreeEntry } -// buildTreesAndBlobs builds the objects and push its to the storer, the hash +// BuildTree builds the tree objects and push its to the storer, the hash // of the root tree is returned. -func (h *commitIndexHelper) buildTreeAndBlobObjects(idx *index.Index) (plumbing.Hash, error) { +func (h *buildTreeHelper) BuildTree(idx *index.Index) (plumbing.Hash, error) { const rootNode = "" h.trees = map[string]*object.Tree{rootNode: {}} h.entries = map[string]*object.TreeEntry{} @@ -130,7 +127,7 @@ func (h *commitIndexHelper) buildTreeAndBlobObjects(idx *index.Index) (plumbing. return h.copyTreeToStorageRecursive(rootNode, h.trees[rootNode]) } -func (h *commitIndexHelper) commitIndexEntry(e *index.Entry) error { +func (h *buildTreeHelper) commitIndexEntry(e *index.Entry) error { parts := strings.Split(e.Name, string(filepath.Separator)) var path string @@ -138,25 +135,19 @@ func (h *commitIndexHelper) commitIndexEntry(e *index.Entry) error { parent := path path = filepath.Join(path, part) - if !h.buildTree(e, parent, path) { - continue - } - - if err := h.copyIndexEntryToStorage(e); err != nil { - return err - } + h.doBuildTree(e, parent, path) } return nil } -func (h *commitIndexHelper) buildTree(e *index.Entry, parent, path string) bool { +func (h *buildTreeHelper) doBuildTree(e *index.Entry, parent, path string) { if _, ok := h.trees[path]; ok { - return false + return } if _, ok := h.entries[path]; ok { - return false + return } te := object.TreeEntry{Name: filepath.Base(path)} @@ -170,84 +161,9 @@ func (h *commitIndexHelper) buildTree(e *index.Entry, parent, path string) bool } h.trees[parent].Entries = append(h.trees[parent].Entries, te) - return true -} - -func (h *commitIndexHelper) copyIndexEntryToStorage(e *index.Entry) error { - _, err := h.s.EncodedObject(plumbing.BlobObject, e.Hash) - if err == nil { - return nil - } - - if err != plumbing.ErrObjectNotFound { - return err - } - - return h.doCopyIndexEntryToStorage(e) -} - -func (h *commitIndexHelper) doCopyIndexEntryToStorage(e *index.Entry) (err error) { - fi, err := h.fs.Lstat(e.Name) - if err != nil { - return err - } - - if fi.Mode()&os.ModeSymlink != 0 { - return h.doCopyIndexEntryFromSymlinkToStorage(e, fi) - } - - obj := h.s.NewEncodedObject() - obj.SetType(plumbing.BlobObject) - obj.SetSize(fi.Size()) - - reader, err := h.fs.Open(e.Name) - if err != nil { - return err - } - - defer ioutil.CheckClose(reader, &err) - - writer, err := obj.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(writer, &err) - - if _, err := io.Copy(writer, reader); err != nil { - return err - } - - _, err = h.s.SetEncodedObject(obj) - return err -} - -func (h *commitIndexHelper) doCopyIndexEntryFromSymlinkToStorage(e *index.Entry, fi os.FileInfo) error { - obj := h.s.NewEncodedObject() - obj.SetType(plumbing.BlobObject) - obj.SetSize(fi.Size()) - - writer, err := obj.Writer() - if err != nil { - return err - } - - defer ioutil.CheckClose(writer, &err) - - target, err := h.fs.Readlink(e.Name) - if err != nil { - return err - } - - if _, err := writer.Write([]byte(target)); err != nil { - return err - } - - _, err = h.s.SetEncodedObject(obj) - return err } -func (h *commitIndexHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) { +func (h *buildTreeHelper) copyTreeToStorageRecursive(parent string, t *object.Tree) (plumbing.Hash, error) { for i, e := range t.Entries { if e.Mode != filemode.Dir && !e.Hash.IsZero() { continue diff --git a/worktree_status.go b/worktree_status.go index 648ea89..7116445 100644 --- a/worktree_status.go +++ b/worktree_status.go @@ -227,7 +227,7 @@ func (w *Worktree) Add(path string) (plumbing.Hash, error) { return plumbing.ZeroHash, err } - h, err := w.calculateBlobHash(path) + h, err := w.copyFileToStorage(path) if err != nil { return h, err } @@ -243,45 +243,59 @@ func (w *Worktree) Add(path string) (plumbing.Hash, error) { return h, err } -func (w *Worktree) calculateBlobHash(filename string) (hash plumbing.Hash, err error) { - fi, err := w.fs.Lstat(filename) +func (w *Worktree) copyFileToStorage(path string) (hash plumbing.Hash, err error) { + fi, err := w.fs.Lstat(path) if err != nil { return plumbing.ZeroHash, err } - if fi.Mode()&os.ModeSymlink != 0 { - return w.calculateBlobHashFromSymlink(filename) - } + obj := w.r.Storer.NewEncodedObject() + obj.SetType(plumbing.BlobObject) + obj.SetSize(fi.Size()) - f, err := w.fs.Open(filename) + writer, err := obj.Writer() if err != nil { return plumbing.ZeroHash, err } - defer ioutil.CheckClose(f, &err) + defer ioutil.CheckClose(writer, &err) + + if fi.Mode()&os.ModeSymlink != 0 { + err = w.fillEncodedObjectFromSymlink(writer, path, fi) + } else { + err = w.fillEncodedObjectFromFile(writer, path, fi) + } - h := plumbing.NewHasher(plumbing.BlobObject, fi.Size()) - if _, err := io.Copy(h, f); err != nil { + if err != nil { return plumbing.ZeroHash, err } - hash = h.Sum() - return + return w.r.Storer.SetEncodedObject(obj) } -func (w *Worktree) calculateBlobHashFromSymlink(link string) (plumbing.Hash, error) { - target, err := w.fs.Readlink(link) +func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer, path string, fi os.FileInfo) (err error) { + src, err := w.fs.Open(path) if err != nil { - return plumbing.ZeroHash, err + return err } - h := plumbing.NewHasher(plumbing.BlobObject, int64(len(target))) - _, err = h.Write([]byte(target)) + defer ioutil.CheckClose(src, &err) + + if _, err := io.Copy(dst, src); err != nil { + return err + } + + return err +} + +func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string, fi os.FileInfo) error { + target, err := w.fs.Readlink(path) if err != nil { - return plumbing.ZeroHash, err + return err } - return h.Sum(), nil + _, err = dst.Write([]byte(target)) + return err } func (w *Worktree) addOrUpdateFileToIndex(filename string, h plumbing.Hash) error { diff --git a/worktree_test.go b/worktree_test.go index 06f82ca..5d0d131 100644 --- a/worktree_test.go +++ b/worktree_test.go @@ -614,6 +614,11 @@ func (s *WorktreeSuite) TestAddUntracked(c *C) { file := status.File("foo") c.Assert(file.Staging, Equals, Added) c.Assert(file.Worktree, Equals, Unmodified) + + obj, err := w.r.Storer.EncodedObject(plumbing.BlobObject, hash) + c.Assert(err, IsNil) + c.Assert(obj, NotNil) + c.Assert(obj.Size(), Equals, int64(3)) } func (s *WorktreeSuite) TestAddModified(c *C) { @@ -690,6 +695,12 @@ func (s *WorktreeSuite) TestAddSymlink(c *C) { h, err = w.Add("bar") c.Assert(err, IsNil) c.Assert(h, Equals, plumbing.NewHash("19102815663d23f8b75a47e7a01965dcdc96468c")) + + obj, err := w.r.Storer.EncodedObject(plumbing.BlobObject, h) + c.Assert(err, IsNil) + c.Assert(obj, NotNil) + c.Assert(obj.Size(), Equals, int64(3)) + } func (s *WorktreeSuite) TestRemove(c *C) { -- cgit