mirror of
https://gitee.com/rainbond/Rainbond.git
synced 2024-12-05 05:07:38 +08:00
1556 lines
37 KiB
Go
1556 lines
37 KiB
Go
package git
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"regexp"
|
|
"runtime"
|
|
|
|
"gopkg.in/src-d/go-git.v4/config"
|
|
"gopkg.in/src-d/go-git.v4/plumbing"
|
|
"gopkg.in/src-d/go-git.v4/plumbing/filemode"
|
|
"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/memory"
|
|
|
|
"golang.org/x/text/unicode/norm"
|
|
. "gopkg.in/check.v1"
|
|
"gopkg.in/src-d/go-billy.v4/memfs"
|
|
"gopkg.in/src-d/go-billy.v4/osfs"
|
|
"gopkg.in/src-d/go-billy.v4/util"
|
|
"gopkg.in/src-d/go-git-fixtures.v3"
|
|
)
|
|
|
|
type WorktreeSuite struct {
|
|
BaseSuite
|
|
}
|
|
|
|
var _ = Suite(&WorktreeSuite{})
|
|
|
|
func (s *WorktreeSuite) SetUpTest(c *C) {
|
|
f := fixtures.Basic().One()
|
|
s.Repository = s.NewRepositoryWithEmptyWorktree(f)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullCheckout(c *C) {
|
|
fs := memfs.New()
|
|
r, _ := Init(memory.NewStorage(), fs)
|
|
r.CreateRemote(&config.RemoteConfig{
|
|
Name: DefaultRemoteName,
|
|
URLs: []string{s.GetBasicLocalRepositoryURL()},
|
|
})
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
fi, err := fs.ReadDir("")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(fi, HasLen, 8)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullFastForward(c *C) {
|
|
url := c.MkDir()
|
|
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
|
|
|
|
server, err := PlainClone(url, false, &CloneOptions{
|
|
URL: path,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
r, err := PlainClone(c.MkDir(), false, &CloneOptions{
|
|
URL: url,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := server.Worktree()
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
|
|
c.Assert(err, IsNil)
|
|
hash, err := w.Commit("foo", &CommitOptions{Author: defaultSignature()})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err = r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
head, err := r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Hash(), Equals, hash)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullNonFastForward(c *C) {
|
|
url := c.MkDir()
|
|
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
|
|
|
|
server, err := PlainClone(url, false, &CloneOptions{
|
|
URL: path,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
r, err := PlainClone(c.MkDir(), false, &CloneOptions{
|
|
URL: url,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := server.Worktree()
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(filepath.Join(path, "foo"), []byte("foo"), 0755)
|
|
c.Assert(err, IsNil)
|
|
_, err = w.Commit("foo", &CommitOptions{Author: defaultSignature()})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err = r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
err = ioutil.WriteFile(filepath.Join(path, "bar"), []byte("bar"), 0755)
|
|
c.Assert(err, IsNil)
|
|
_, err = w.Commit("bar", &CommitOptions{Author: defaultSignature()})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, ErrorMatches, "non-fast-forward update")
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullUpdateReferencesIfNeeded(c *C) {
|
|
r, _ := Init(memory.NewStorage(), memfs.New())
|
|
r.CreateRemote(&config.RemoteConfig{
|
|
Name: DefaultRemoteName,
|
|
URLs: []string{s.GetBasicLocalRepositoryURL()},
|
|
})
|
|
|
|
err := r.Fetch(&FetchOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
_, err = r.Reference("refs/heads/master", false)
|
|
c.Assert(err, NotNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
head, err := r.Reference(plumbing.HEAD, true)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
|
|
|
|
branch, err := r.Reference("refs/heads/master", false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, Equals, NoErrAlreadyUpToDate)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullInSingleBranch(c *C) {
|
|
r, _ := Init(memory.NewStorage(), memfs.New())
|
|
err := r.clone(context.Background(), &CloneOptions{
|
|
URL: s.GetBasicLocalRepositoryURL(),
|
|
SingleBranch: true,
|
|
})
|
|
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{})
|
|
c.Assert(err, Equals, NoErrAlreadyUpToDate)
|
|
|
|
branch, err := r.Reference("refs/heads/master", false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
|
|
|
|
branch, err = r.Reference("refs/remotes/foo/branch", false)
|
|
c.Assert(err, NotNil)
|
|
|
|
storage := r.Storer.(*memory.Storage)
|
|
c.Assert(storage.Objects, HasLen, 28)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullProgress(c *C) {
|
|
r, _ := Init(memory.NewStorage(), memfs.New())
|
|
|
|
r.CreateRemote(&config.RemoteConfig{
|
|
Name: DefaultRemoteName,
|
|
URLs: []string{s.GetBasicLocalRepositoryURL()},
|
|
})
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
buf := bytes.NewBuffer(nil)
|
|
err = w.Pull(&PullOptions{
|
|
Progress: buf,
|
|
})
|
|
|
|
c.Assert(err, IsNil)
|
|
c.Assert(buf.Len(), Not(Equals), 0)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestPullProgressWithRecursion(c *C) {
|
|
path := fixtures.ByTag("submodule").One().Worktree().Root()
|
|
|
|
dir, err := ioutil.TempDir("", "plain-clone-submodule")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
r, _ := PlainInit(dir, false)
|
|
r.CreateRemote(&config.RemoteConfig{
|
|
Name: DefaultRemoteName,
|
|
URLs: []string{path},
|
|
})
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{
|
|
RecurseSubmodules: DefaultSubmoduleRecursionDepth,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
cfg, err := r.Config()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(cfg.Submodules, HasLen, 2)
|
|
}
|
|
|
|
func (s *RepositorySuite) TestPullAdd(c *C) {
|
|
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
|
|
|
|
r, err := Clone(memory.NewStorage(), memfs.New(), &CloneOptions{
|
|
URL: filepath.Join(path, ".git"),
|
|
})
|
|
|
|
c.Assert(err, IsNil)
|
|
|
|
storage := r.Storer.(*memory.Storage)
|
|
c.Assert(storage.Objects, HasLen, 28)
|
|
|
|
branch, err := r.Reference("refs/heads/master", false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash().String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
|
|
|
|
ExecuteOnPath(c, path,
|
|
"touch foo",
|
|
"git add foo",
|
|
"git commit -m foo foo",
|
|
)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Pull(&PullOptions{RemoteName: "origin"})
|
|
c.Assert(err, IsNil)
|
|
|
|
// the commit command has introduced a new commit, tree and blob
|
|
c.Assert(storage.Objects, HasLen, 31)
|
|
|
|
branch, err = r.Reference("refs/heads/master", false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash().String(), Not(Equals), "6ecf0ef2c2dffb796033e5a02219af86ec6584e5")
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckout(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Force: true,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
entries, err := fs.ReadDir("/")
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(entries, HasLen, 8)
|
|
ch, err := fs.Open("CHANGELOG")
|
|
c.Assert(err, IsNil)
|
|
|
|
content, err := ioutil.ReadAll(ch)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(string(content), Equals, "Initial changelog\n")
|
|
|
|
idx, err := s.Repository.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutForce(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
w.Filesystem = memfs.New()
|
|
|
|
err = w.Checkout(&CheckoutOptions{
|
|
Force: true,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
entries, err := w.Filesystem.ReadDir("/")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(entries, HasLen, 8)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutSymlink(c *C) {
|
|
if runtime.GOOS == "windows" {
|
|
c.Skip("git doesn't support symlinks by default in windows")
|
|
}
|
|
|
|
dir, err := ioutil.TempDir("", "checkout")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
r, err := PlainInit(dir, false)
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
w.Filesystem.Symlink("not-exists", "bar")
|
|
w.Add("bar")
|
|
w.Commit("foo", &CommitOptions{Author: defaultSignature()})
|
|
|
|
r.Storer.SetIndex(&index.Index{Version: 2})
|
|
w.Filesystem = osfs.New(filepath.Join(dir, "worktree-empty"))
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
|
|
target, err := w.Filesystem.Readlink("bar")
|
|
c.Assert(target, Equals, "not-exists")
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestFilenameNormalization(c *C) {
|
|
if runtime.GOOS == "windows" {
|
|
c.Skip("windows paths may contain non utf-8 sequences")
|
|
}
|
|
|
|
url := c.MkDir()
|
|
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
|
|
|
|
server, err := PlainClone(url, false, &CloneOptions{
|
|
URL: path,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
filename := "페"
|
|
|
|
w, err := server.Worktree()
|
|
c.Assert(err, IsNil)
|
|
util.WriteFile(w.Filesystem, filename, []byte("foo"), 0755)
|
|
_, err = w.Add(filename)
|
|
c.Assert(err, IsNil)
|
|
_, err = w.Commit("foo", &CommitOptions{Author: defaultSignature()})
|
|
c.Assert(err, IsNil)
|
|
|
|
r, err := Clone(memory.NewStorage(), memfs.New(), &CloneOptions{
|
|
URL: url,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err = r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
|
|
err = w.Filesystem.Remove(filename)
|
|
c.Assert(err, IsNil)
|
|
|
|
modFilename := norm.Form(norm.NFKD).String(filename)
|
|
util.WriteFile(w.Filesystem, modFilename, []byte("foo"), 0755)
|
|
|
|
_, err = w.Add(filename)
|
|
c.Assert(err, IsNil)
|
|
_, err = w.Add(modFilename)
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err = w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutSubmodule(c *C) {
|
|
url := "https://github.com/git-fixtures/submodule.git"
|
|
r := s.NewRepositoryWithEmptyWorktree(fixtures.ByURL(url).One())
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutSubmoduleInitialized(c *C) {
|
|
url := "https://github.com/git-fixtures/submodule.git"
|
|
r := s.NewRepository(fixtures.ByURL(url).One())
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
sub, err := w.Submodules()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = sub.Update(&SubmoduleUpdateOptions{Init: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutIndexMem(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
idx, err := s.Repository.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
c.Assert(idx.Entries[0].Hash.String(), Equals, "32858aad3c383ed1ff0a0f9bdf231d54a00c9e88")
|
|
c.Assert(idx.Entries[0].Name, Equals, ".gitignore")
|
|
c.Assert(idx.Entries[0].Mode, Equals, filemode.Regular)
|
|
c.Assert(idx.Entries[0].ModifiedAt.IsZero(), Equals, false)
|
|
c.Assert(idx.Entries[0].Size, Equals, uint32(189))
|
|
|
|
// ctime, dev, inode, uid and gid are not supported on memfs fs
|
|
c.Assert(idx.Entries[0].CreatedAt.IsZero(), Equals, true)
|
|
c.Assert(idx.Entries[0].Dev, Equals, uint32(0))
|
|
c.Assert(idx.Entries[0].Inode, Equals, uint32(0))
|
|
c.Assert(idx.Entries[0].UID, Equals, uint32(0))
|
|
c.Assert(idx.Entries[0].GID, Equals, uint32(0))
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutIndexOS(c *C) {
|
|
dir, err := ioutil.TempDir("", "checkout")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
fs := osfs.New(filepath.Join(dir, "worktree"))
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
idx, err := s.Repository.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
c.Assert(idx.Entries[0].Hash.String(), Equals, "32858aad3c383ed1ff0a0f9bdf231d54a00c9e88")
|
|
c.Assert(idx.Entries[0].Name, Equals, ".gitignore")
|
|
c.Assert(idx.Entries[0].Mode, Equals, filemode.Regular)
|
|
c.Assert(idx.Entries[0].ModifiedAt.IsZero(), Equals, false)
|
|
c.Assert(idx.Entries[0].Size, Equals, uint32(189))
|
|
|
|
c.Assert(idx.Entries[0].CreatedAt.IsZero(), Equals, false)
|
|
if runtime.GOOS != "windows" {
|
|
c.Assert(idx.Entries[0].Dev, Not(Equals), uint32(0))
|
|
c.Assert(idx.Entries[0].Inode, Not(Equals), uint32(0))
|
|
c.Assert(idx.Entries[0].UID, Not(Equals), uint32(0))
|
|
c.Assert(idx.Entries[0].GID, Not(Equals), uint32(0))
|
|
}
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutBranch(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Branch: "refs/heads/branch",
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
head, err := w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "refs/heads/branch")
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutCreateWithHash(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Create: true,
|
|
Branch: "refs/heads/foo",
|
|
Hash: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
head, err := w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "refs/heads/foo")
|
|
c.Assert(head.Hash(), Equals, plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"))
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutCreate(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Create: true,
|
|
Branch: "refs/heads/foo",
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
head, err := w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "refs/heads/foo")
|
|
c.Assert(head.Hash(), Equals, plumbing.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"))
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutBranchAndHash(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Branch: "refs/heads/foo",
|
|
Hash: plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9"),
|
|
})
|
|
|
|
c.Assert(err, Equals, ErrBranchHashExclusive)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutCreateMissingBranch(c *C) {
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: memfs.New(),
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{
|
|
Create: true,
|
|
})
|
|
|
|
c.Assert(err, Equals, ErrCreateRequiresBranch)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutTag(c *C) {
|
|
f := fixtures.ByTag("tags").One()
|
|
r := s.NewRepositoryWithEmptyWorktree(f)
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
head, err := w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "refs/heads/master")
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
|
|
err = w.Checkout(&CheckoutOptions{Branch: "refs/tags/lightweight-tag"})
|
|
c.Assert(err, IsNil)
|
|
head, err = w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "HEAD")
|
|
c.Assert(head.Hash().String(), Equals, "f7b877701fbf855b44c0a9e86f3fdce2c298b07f")
|
|
|
|
err = w.Checkout(&CheckoutOptions{Branch: "refs/tags/commit-tag"})
|
|
c.Assert(err, IsNil)
|
|
head, err = w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "HEAD")
|
|
c.Assert(head.Hash().String(), Equals, "f7b877701fbf855b44c0a9e86f3fdce2c298b07f")
|
|
|
|
err = w.Checkout(&CheckoutOptions{Branch: "refs/tags/tree-tag"})
|
|
c.Assert(err, NotNil)
|
|
head, err = w.r.Head()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(head.Name().String(), Equals, "HEAD")
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutBisect(c *C) {
|
|
s.testCheckoutBisect(c, "https://github.com/src-d/go-git.git")
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestCheckoutBisectSubmodules(c *C) {
|
|
s.testCheckoutBisect(c, "https://github.com/git-fixtures/submodule.git")
|
|
}
|
|
|
|
// TestCheckoutBisect simulates a git bisect going through the git history and
|
|
// checking every commit over the previous commit
|
|
func (s *WorktreeSuite) testCheckoutBisect(c *C, url string) {
|
|
f := fixtures.ByURL(url).One()
|
|
r := s.NewRepositoryWithEmptyWorktree(f)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
iter, err := w.r.Log(&LogOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
iter.ForEach(func(commit *object.Commit) error {
|
|
err := w.Checkout(&CheckoutOptions{Hash: commit.Hash})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatus(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status, HasLen, 9)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusEmpty(c *C) {
|
|
fs := memfs.New()
|
|
storage := memory.NewStorage()
|
|
|
|
r, err := Init(storage, fs)
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
c.Assert(status, NotNil)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusEmptyDirty(c *C) {
|
|
fs := memfs.New()
|
|
err := util.WriteFile(fs, "foo", []byte("foo"), 0755)
|
|
c.Assert(err, IsNil)
|
|
|
|
storage := memory.NewStorage()
|
|
|
|
r, err := Init(storage, fs)
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status, HasLen, 1)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestReset(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err := w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Not(Equals), commit)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: MergeReset, Commit: commit})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err = w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commit)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestResetWithUntracked(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = util.WriteFile(fs, "foo", nil, 0755)
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: MergeReset, Commit: commit})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestResetSoft(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: SoftReset, Commit: commit})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err := w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commit)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status.File("CHANGELOG").Staging, Equals, Added)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestResetMixed(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: MixedReset, Commit: commit})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err := w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commit)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status.File("CHANGELOG").Staging, Equals, Untracked)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestResetMerge(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commitA := plumbing.NewHash("918c48b83bd081e863dbe1b80f8998f058cd8294")
|
|
commitB := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: MergeReset, Commit: commitA})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err := w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commitA)
|
|
|
|
f, err := fs.Create(".gitignore")
|
|
c.Assert(err, IsNil)
|
|
_, err = f.Write([]byte("foo"))
|
|
c.Assert(err, IsNil)
|
|
err = f.Close()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: MergeReset, Commit: commitB})
|
|
c.Assert(err, Equals, ErrUnstagedChanges)
|
|
|
|
branch, err = w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commitA)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestResetHard(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
commit := plumbing.NewHash("35e85108805c84807bc66a02d91535e1e24b38b9")
|
|
|
|
err := w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
f, err := fs.Create(".gitignore")
|
|
c.Assert(err, IsNil)
|
|
_, err = f.Write([]byte("foo"))
|
|
c.Assert(err, IsNil)
|
|
err = f.Close()
|
|
c.Assert(err, IsNil)
|
|
|
|
err = w.Reset(&ResetOptions{Mode: HardReset, Commit: commit})
|
|
c.Assert(err, IsNil)
|
|
|
|
branch, err := w.r.Reference(plumbing.Master, false)
|
|
c.Assert(err, IsNil)
|
|
c.Assert(branch.Hash(), Equals, commit)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusAfterCheckout(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, true)
|
|
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusModified(c *C) {
|
|
dir, err := ioutil.TempDir("", "status")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
fs := osfs.New(filepath.Join(dir, "worktree"))
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
f, err := fs.Create(".gitignore")
|
|
c.Assert(err, IsNil)
|
|
_, err = f.Write([]byte("foo"))
|
|
c.Assert(err, IsNil)
|
|
err = f.Close()
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status.File(".gitignore").Worktree, Equals, Modified)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusIgnored(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
w.Checkout(&CheckoutOptions{})
|
|
|
|
fs.MkdirAll("another", os.ModePerm)
|
|
f, _ := fs.Create("another/file")
|
|
f.Close()
|
|
fs.MkdirAll("vendor/github.com", os.ModePerm)
|
|
f, _ = fs.Create("vendor/github.com/file")
|
|
f.Close()
|
|
fs.MkdirAll("vendor/gopkg.in", os.ModePerm)
|
|
f, _ = fs.Create("vendor/gopkg.in/file")
|
|
f.Close()
|
|
|
|
status, _ := w.Status()
|
|
c.Assert(len(status), Equals, 3)
|
|
_, ok := status["another/file"]
|
|
c.Assert(ok, Equals, true)
|
|
_, ok = status["vendor/github.com/file"]
|
|
c.Assert(ok, Equals, true)
|
|
_, ok = status["vendor/gopkg.in/file"]
|
|
c.Assert(ok, Equals, true)
|
|
|
|
f, _ = fs.Create(".gitignore")
|
|
f.Write([]byte("vendor/g*/"))
|
|
f.Close()
|
|
f, _ = fs.Create("vendor/.gitignore")
|
|
f.Write([]byte("!github.com/\n"))
|
|
f.Close()
|
|
|
|
status, _ = w.Status()
|
|
c.Assert(len(status), Equals, 4)
|
|
_, ok = status[".gitignore"]
|
|
c.Assert(ok, Equals, true)
|
|
_, ok = status["another/file"]
|
|
c.Assert(ok, Equals, true)
|
|
_, ok = status["vendor/.gitignore"]
|
|
c.Assert(ok, Equals, true)
|
|
_, ok = status["vendor/github.com/file"]
|
|
c.Assert(ok, Equals, true)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusUntracked(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
f, err := w.Filesystem.Create("foo")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(f.Close(), IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.File("foo").Staging, Equals, Untracked)
|
|
c.Assert(status.File("foo").Worktree, Equals, Untracked)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestStatusDeleted(c *C) {
|
|
dir, err := ioutil.TempDir("", "status")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
fs := osfs.New(filepath.Join(dir, "worktree"))
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err = w.Checkout(&CheckoutOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = fs.Remove(".gitignore")
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status.IsClean(), Equals, false)
|
|
c.Assert(status.File(".gitignore").Worktree, Equals, Deleted)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestSubmodule(c *C) {
|
|
path := fixtures.ByTag("submodule").One().Worktree().Root()
|
|
r, err := PlainOpen(path)
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
m, err := w.Submodule("basic")
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(m.Config().Name, Equals, "basic")
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestSubmodules(c *C) {
|
|
path := fixtures.ByTag("submodule").One().Worktree().Root()
|
|
r, err := PlainOpen(path)
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
l, err := w.Submodules()
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(l, HasLen, 2)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestAddUntracked(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
idx, err := w.r.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
|
|
err = util.WriteFile(w.Filesystem, "foo", []byte("FOO"), 0755)
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Add("foo")
|
|
c.Assert(hash.String(), Equals, "d96c7efbfec2814ae0301ad054dc8d9fc416c9b5")
|
|
c.Assert(err, IsNil)
|
|
|
|
idx, err = w.r.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 10)
|
|
|
|
e, err := idx.Entry("foo")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(e.Hash, Equals, hash)
|
|
c.Assert(e.Mode, Equals, filemode.Executable)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status, HasLen, 1)
|
|
|
|
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) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
idx, err := w.r.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
|
|
err = util.WriteFile(w.Filesystem, "LICENSE", []byte("FOO"), 0644)
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Add("LICENSE")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(hash.String(), Equals, "d96c7efbfec2814ae0301ad054dc8d9fc416c9b5")
|
|
|
|
idx, err = w.r.Storer.Index()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(idx.Entries, HasLen, 9)
|
|
|
|
e, err := idx.Entry("LICENSE")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(e.Hash, Equals, hash)
|
|
c.Assert(e.Mode, Equals, filemode.Regular)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status, HasLen, 1)
|
|
|
|
file := status.File("LICENSE")
|
|
c.Assert(file.Staging, Equals, Modified)
|
|
c.Assert(file.Worktree, Equals, Unmodified)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestAddUnmodified(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Add("LICENSE")
|
|
c.Assert(hash.String(), Equals, "c192bd6a24ea1ab01d78686e417c8bdc7c3d197f")
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestAddSymlink(c *C) {
|
|
dir, err := ioutil.TempDir("", "checkout")
|
|
c.Assert(err, IsNil)
|
|
defer os.RemoveAll(dir)
|
|
|
|
r, err := PlainInit(dir, false)
|
|
c.Assert(err, IsNil)
|
|
err = util.WriteFile(r.wt, "foo", []byte("qux"), 0644)
|
|
c.Assert(err, IsNil)
|
|
err = r.wt.Symlink("foo", "bar")
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
h, err := w.Add("foo")
|
|
c.Assert(err, IsNil)
|
|
c.Assert(h, Not(Equals), plumbing.NewHash("19102815663d23f8b75a47e7a01965dcdc96468c"))
|
|
|
|
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) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Remove("LICENSE")
|
|
c.Assert(hash.String(), Equals, "c192bd6a24ea1ab01d78686e417c8bdc7c3d197f")
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status, HasLen, 1)
|
|
c.Assert(status.File("LICENSE").Staging, Equals, Deleted)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestRemoveNotExistentEntry(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Remove("not-exists")
|
|
c.Assert(hash.IsZero(), Equals, true)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestRemoveDeletedFromWorktree(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
err = fs.Remove("LICENSE")
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Remove("LICENSE")
|
|
c.Assert(hash.String(), Equals, "c192bd6a24ea1ab01d78686e417c8bdc7c3d197f")
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status, HasLen, 1)
|
|
c.Assert(status.File("LICENSE").Staging, Equals, Deleted)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestMove(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Move("LICENSE", "foo")
|
|
c.Check(hash.String(), Equals, "c192bd6a24ea1ab01d78686e417c8bdc7c3d197f")
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err := w.Status()
|
|
c.Assert(err, IsNil)
|
|
c.Assert(status, HasLen, 2)
|
|
c.Assert(status.File("LICENSE").Staging, Equals, Deleted)
|
|
c.Assert(status.File("foo").Staging, Equals, Added)
|
|
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestMoveNotExistentEntry(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Move("not-exists", "foo")
|
|
c.Assert(hash.IsZero(), Equals, true)
|
|
c.Assert(err, NotNil)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestMoveToExistent(c *C) {
|
|
fs := memfs.New()
|
|
w := &Worktree{
|
|
r: s.Repository,
|
|
Filesystem: fs,
|
|
}
|
|
|
|
err := w.Checkout(&CheckoutOptions{Force: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
hash, err := w.Move(".gitignore", "LICENSE")
|
|
c.Assert(hash.IsZero(), Equals, true)
|
|
c.Assert(err, Equals, ErrDestinationExists)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestClean(c *C) {
|
|
fs := fixtures.ByTag("dirty").One().Worktree()
|
|
|
|
// Open the repo.
|
|
fs, err := fs.Chroot("repo")
|
|
c.Assert(err, IsNil)
|
|
r, err := PlainOpen(fs.Root())
|
|
c.Assert(err, IsNil)
|
|
|
|
wt, err := r.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
// Status before cleaning.
|
|
status, err := wt.Status()
|
|
c.Assert(len(status), Equals, 2)
|
|
|
|
err = wt.Clean(&CleanOptions{})
|
|
c.Assert(err, IsNil)
|
|
|
|
// Status after cleaning.
|
|
status, err = wt.Status()
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(len(status), Equals, 1)
|
|
|
|
// Clean with Dir: true.
|
|
err = wt.Clean(&CleanOptions{Dir: true})
|
|
c.Assert(err, IsNil)
|
|
|
|
status, err = wt.Status()
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(len(status), Equals, 0)
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestAlternatesRepo(c *C) {
|
|
fs := fixtures.ByTag("alternates").One().Worktree()
|
|
|
|
// Open 1st repo.
|
|
rep1fs, err := fs.Chroot("rep1")
|
|
c.Assert(err, IsNil)
|
|
rep1, err := PlainOpen(rep1fs.Root())
|
|
c.Assert(err, IsNil)
|
|
|
|
// Open 2nd repo.
|
|
rep2fs, err := fs.Chroot("rep2")
|
|
c.Assert(err, IsNil)
|
|
rep2, err := PlainOpen(rep2fs.Root())
|
|
c.Assert(err, IsNil)
|
|
|
|
// Get the HEAD commit from the main repo.
|
|
h, err := rep1.Head()
|
|
c.Assert(err, IsNil)
|
|
commit1, err := rep1.CommitObject(h.Hash())
|
|
c.Assert(err, IsNil)
|
|
|
|
// Get the HEAD commit from the shared repo.
|
|
h, err = rep2.Head()
|
|
c.Assert(err, IsNil)
|
|
commit2, err := rep2.CommitObject(h.Hash())
|
|
c.Assert(err, IsNil)
|
|
|
|
c.Assert(commit1.String(), Equals, commit2.String())
|
|
}
|
|
|
|
func (s *WorktreeSuite) TestGrep(c *C) {
|
|
cases := []struct {
|
|
name string
|
|
options GrepOptions
|
|
wantResult []GrepResult
|
|
dontWantResult []GrepResult
|
|
wantError error
|
|
}{
|
|
{
|
|
name: "basic word match",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "case insensitive match",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile(`(?i)IMport`)},
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "invert match",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
InvertMatch: true,
|
|
},
|
|
dontWantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "match at a given commit hash",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("The MIT License")},
|
|
CommitHash: plumbing.NewHash("b029517f6300c2da0f4b651b8642506cd6aaf45d"),
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "LICENSE",
|
|
LineNumber: 1,
|
|
Content: "The MIT License (MIT)",
|
|
TreeName: "b029517f6300c2da0f4b651b8642506cd6aaf45d",
|
|
},
|
|
},
|
|
dontWantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "match for a given pathspec",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
PathSpecs: []*regexp.Regexp{regexp.MustCompile("go/")},
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
dontWantResult: []GrepResult{
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "match at a given reference name",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
ReferenceName: "refs/heads/master",
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "refs/heads/master",
|
|
},
|
|
},
|
|
}, {
|
|
name: "ambiguous options",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
CommitHash: plumbing.NewHash("2d55a722f3c3ecc36da919dfd8b6de38352f3507"),
|
|
ReferenceName: "somereferencename",
|
|
},
|
|
wantError: ErrHashOrReference,
|
|
}, {
|
|
name: "multiple patterns",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{
|
|
regexp.MustCompile("import"),
|
|
regexp.MustCompile("License"),
|
|
},
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "LICENSE",
|
|
LineNumber: 1,
|
|
Content: "The MIT License (MIT)",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
}, {
|
|
name: "multiple pathspecs",
|
|
options: GrepOptions{
|
|
Patterns: []*regexp.Regexp{regexp.MustCompile("import")},
|
|
PathSpecs: []*regexp.Regexp{
|
|
regexp.MustCompile("go/"),
|
|
regexp.MustCompile("vendor/"),
|
|
},
|
|
},
|
|
wantResult: []GrepResult{
|
|
{
|
|
FileName: "go/example.go",
|
|
LineNumber: 3,
|
|
Content: "import (",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
{
|
|
FileName: "vendor/foo.go",
|
|
LineNumber: 3,
|
|
Content: "import \"fmt\"",
|
|
TreeName: "6ecf0ef2c2dffb796033e5a02219af86ec6584e5",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
path := fixtures.Basic().ByTag("worktree").One().Worktree().Root()
|
|
server, err := PlainClone(c.MkDir(), false, &CloneOptions{
|
|
URL: path,
|
|
})
|
|
c.Assert(err, IsNil)
|
|
|
|
w, err := server.Worktree()
|
|
c.Assert(err, IsNil)
|
|
|
|
for _, tc := range cases {
|
|
gr, err := w.Grep(&tc.options)
|
|
if tc.wantError != nil {
|
|
c.Assert(err, Equals, tc.wantError)
|
|
} else {
|
|
c.Assert(err, IsNil)
|
|
}
|
|
|
|
// Iterate through the results and check if the wanted result is present
|
|
// in the got result.
|
|
for _, wantResult := range tc.wantResult {
|
|
found := false
|
|
for _, gotResult := range gr {
|
|
if wantResult == gotResult {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
c.Errorf("unexpected grep results for %q, expected result to contain: %v", tc.name, wantResult)
|
|
}
|
|
}
|
|
|
|
// Iterate through the results and check if the not wanted result is
|
|
// present in the got result.
|
|
for _, dontWantResult := range tc.dontWantResult {
|
|
found := false
|
|
for _, gotResult := range gr {
|
|
if dontWantResult == gotResult {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if found {
|
|
c.Errorf("unexpected grep results for %q, expected result to NOT contain: %v", tc.name, dontWantResult)
|
|
}
|
|
}
|
|
}
|
|
}
|