fork of go-git with some jj specific features
at v4.6.0 316 lines 9.6 kB view raw
1package git 2 3import ( 4 "bytes" 5 "strings" 6 "time" 7 8 "golang.org/x/crypto/openpgp" 9 "golang.org/x/crypto/openpgp/armor" 10 "golang.org/x/crypto/openpgp/errors" 11 "gopkg.in/src-d/go-git.v4/plumbing" 12 "gopkg.in/src-d/go-git.v4/plumbing/object" 13 "gopkg.in/src-d/go-git.v4/plumbing/storer" 14 "gopkg.in/src-d/go-git.v4/storage/memory" 15 16 . "gopkg.in/check.v1" 17 "gopkg.in/src-d/go-billy.v4/memfs" 18 "gopkg.in/src-d/go-billy.v4/util" 19) 20 21func (s *WorktreeSuite) TestCommitInvalidOptions(c *C) { 22 r, err := Init(memory.NewStorage(), memfs.New()) 23 c.Assert(err, IsNil) 24 25 w, err := r.Worktree() 26 c.Assert(err, IsNil) 27 28 hash, err := w.Commit("", &CommitOptions{}) 29 c.Assert(err, Equals, ErrMissingAuthor) 30 c.Assert(hash.IsZero(), Equals, true) 31} 32 33func (s *WorktreeSuite) TestCommitInitial(c *C) { 34 expected := plumbing.NewHash("98c4ac7c29c913f7461eae06e024dc18e80d23a4") 35 36 fs := memfs.New() 37 storage := memory.NewStorage() 38 39 r, err := Init(storage, fs) 40 c.Assert(err, IsNil) 41 42 w, err := r.Worktree() 43 c.Assert(err, IsNil) 44 45 util.WriteFile(fs, "foo", []byte("foo"), 0644) 46 47 _, err = w.Add("foo") 48 c.Assert(err, IsNil) 49 50 hash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature()}) 51 c.Assert(hash, Equals, expected) 52 c.Assert(err, IsNil) 53 54 assertStorageStatus(c, r, 1, 1, 1, expected) 55} 56 57func (s *WorktreeSuite) TestCommitParent(c *C) { 58 expected := plumbing.NewHash("ef3ca05477530b37f48564be33ddd48063fc7a22") 59 60 fs := memfs.New() 61 w := &Worktree{ 62 r: s.Repository, 63 Filesystem: fs, 64 } 65 66 err := w.Checkout(&CheckoutOptions{}) 67 c.Assert(err, IsNil) 68 69 util.WriteFile(fs, "foo", []byte("foo"), 0644) 70 71 _, err = w.Add("foo") 72 c.Assert(err, IsNil) 73 74 hash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature()}) 75 c.Assert(hash, Equals, expected) 76 c.Assert(err, IsNil) 77 78 assertStorageStatus(c, s.Repository, 13, 11, 10, expected) 79} 80 81func (s *WorktreeSuite) TestCommitAll(c *C) { 82 expected := plumbing.NewHash("aede6f8c9c1c7ec9ca8d287c64b8ed151276fa28") 83 84 fs := memfs.New() 85 w := &Worktree{ 86 r: s.Repository, 87 Filesystem: fs, 88 } 89 90 err := w.Checkout(&CheckoutOptions{}) 91 c.Assert(err, IsNil) 92 93 util.WriteFile(fs, "LICENSE", []byte("foo"), 0644) 94 util.WriteFile(fs, "foo", []byte("foo"), 0644) 95 96 hash, err := w.Commit("foo\n", &CommitOptions{ 97 All: true, 98 Author: defaultSignature(), 99 }) 100 101 c.Assert(hash, Equals, expected) 102 c.Assert(err, IsNil) 103 104 assertStorageStatus(c, s.Repository, 13, 11, 10, expected) 105} 106 107func (s *WorktreeSuite) TestRemoveAndCommitAll(c *C) { 108 expected := plumbing.NewHash("907cd576c6ced2ecd3dab34a72bf9cf65944b9a9") 109 110 fs := memfs.New() 111 w := &Worktree{ 112 r: s.Repository, 113 Filesystem: fs, 114 } 115 116 err := w.Checkout(&CheckoutOptions{}) 117 c.Assert(err, IsNil) 118 119 util.WriteFile(fs, "foo", []byte("foo"), 0644) 120 _, err = w.Add("foo") 121 c.Assert(err, IsNil) 122 123 _, errFirst := w.Commit("Add in Repo\n", &CommitOptions{ 124 Author: defaultSignature(), 125 }) 126 c.Assert(errFirst, IsNil) 127 128 errRemove := fs.Remove("foo") 129 c.Assert(errRemove, IsNil) 130 131 hash, errSecond := w.Commit("Remove foo\n", &CommitOptions{ 132 All: true, 133 Author: defaultSignature(), 134 }) 135 c.Assert(errSecond, IsNil) 136 137 c.Assert(hash, Equals, expected) 138 c.Assert(err, IsNil) 139 140 assertStorageStatus(c, s.Repository, 13, 11, 11, expected) 141} 142 143func (s *WorktreeSuite) TestCommitSign(c *C) { 144 fs := memfs.New() 145 storage := memory.NewStorage() 146 147 r, err := Init(storage, fs) 148 c.Assert(err, IsNil) 149 150 w, err := r.Worktree() 151 c.Assert(err, IsNil) 152 153 util.WriteFile(fs, "foo", []byte("foo"), 0644) 154 155 _, err = w.Add("foo") 156 c.Assert(err, IsNil) 157 158 key := commitSignKey(c, true) 159 hash, err := w.Commit("foo\n", &CommitOptions{Author: defaultSignature(), SignKey: key}) 160 c.Assert(err, IsNil) 161 162 // Verify the commit. 163 pks := new(bytes.Buffer) 164 pkw, err := armor.Encode(pks, openpgp.PublicKeyType, nil) 165 c.Assert(err, IsNil) 166 167 err = key.Serialize(pkw) 168 c.Assert(err, IsNil) 169 err = pkw.Close() 170 c.Assert(err, IsNil) 171 172 expectedCommit, err := r.CommitObject(hash) 173 c.Assert(err, IsNil) 174 actual, err := expectedCommit.Verify(pks.String()) 175 c.Assert(err, IsNil) 176 c.Assert(actual.PrimaryKey, DeepEquals, key.PrimaryKey) 177} 178 179func (s *WorktreeSuite) TestCommitSignBadKey(c *C) { 180 fs := memfs.New() 181 storage := memory.NewStorage() 182 183 r, err := Init(storage, fs) 184 c.Assert(err, IsNil) 185 186 w, err := r.Worktree() 187 c.Assert(err, IsNil) 188 189 util.WriteFile(fs, "foo", []byte("foo"), 0644) 190 191 _, err = w.Add("foo") 192 c.Assert(err, IsNil) 193 194 key := commitSignKey(c, false) 195 _, err = w.Commit("foo\n", &CommitOptions{Author: defaultSignature(), SignKey: key}) 196 c.Assert(err, Equals, errors.InvalidArgumentError("signing key is encrypted")) 197} 198 199func assertStorageStatus( 200 c *C, r *Repository, 201 treesCount, blobCount, commitCount int, head plumbing.Hash, 202) { 203 trees, err := r.Storer.IterEncodedObjects(plumbing.TreeObject) 204 c.Assert(err, IsNil) 205 blobs, err := r.Storer.IterEncodedObjects(plumbing.BlobObject) 206 c.Assert(err, IsNil) 207 commits, err := r.Storer.IterEncodedObjects(plumbing.CommitObject) 208 c.Assert(err, IsNil) 209 210 c.Assert(lenIterEncodedObjects(trees), Equals, treesCount) 211 c.Assert(lenIterEncodedObjects(blobs), Equals, blobCount) 212 c.Assert(lenIterEncodedObjects(commits), Equals, commitCount) 213 214 ref, err := r.Head() 215 c.Assert(err, IsNil) 216 c.Assert(ref.Hash(), Equals, head) 217} 218 219func lenIterEncodedObjects(iter storer.EncodedObjectIter) int { 220 count := 0 221 iter.ForEach(func(plumbing.EncodedObject) error { 222 count++ 223 return nil 224 }) 225 226 return count 227} 228 229func defaultSignature() *object.Signature { 230 when, _ := time.Parse(object.DateFormat, "Thu May 04 00:03:43 2017 +0200") 231 return &object.Signature{ 232 Name: "foo", 233 Email: "foo@foo.foo", 234 When: when, 235 } 236} 237 238func commitSignKey(c *C, decrypt bool) *openpgp.Entity { 239 s := strings.NewReader(armoredKeyRing) 240 es, err := openpgp.ReadArmoredKeyRing(s) 241 c.Assert(err, IsNil) 242 243 c.Assert(es, HasLen, 1) 244 c.Assert(es[0].Identities, HasLen, 1) 245 _, ok := es[0].Identities["foo bar <foo@foo.foo>"] 246 c.Assert(ok, Equals, true) 247 248 key := es[0] 249 if decrypt { 250 err = key.PrivateKey.Decrypt([]byte(keyPassphrase)) 251 c.Assert(err, IsNil) 252 } 253 254 return key 255} 256 257const armoredKeyRing = ` 258-----BEGIN PGP PRIVATE KEY BLOCK----- 259 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 312=8g3t 313-----END PGP PRIVATE KEY BLOCK----- 314` 315 316const keyPassphrase = "abcdef0123456789"