fork of go-git with some jj specific features
at v4.2.0 22 kB view raw
1package git 2 3import ( 4 "bytes" 5 "context" 6 "io" 7 "io/ioutil" 8 "os" 9 10 "gopkg.in/src-d/go-git.v4/config" 11 "gopkg.in/src-d/go-git.v4/plumbing" 12 "gopkg.in/src-d/go-git.v4/plumbing/storer" 13 "gopkg.in/src-d/go-git.v4/storage" 14 "gopkg.in/src-d/go-git.v4/storage/filesystem" 15 "gopkg.in/src-d/go-git.v4/storage/memory" 16 17 . "gopkg.in/check.v1" 18 "gopkg.in/src-d/go-billy.v4/osfs" 19 "gopkg.in/src-d/go-git-fixtures.v3" 20) 21 22type RemoteSuite struct { 23 BaseSuite 24} 25 26var _ = Suite(&RemoteSuite{}) 27 28func (s *RemoteSuite) TestFetchInvalidEndpoint(c *C) { 29 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"http://\\"}}) 30 err := r.Fetch(&FetchOptions{RemoteName: "foo"}) 31 c.Assert(err, ErrorMatches, ".*invalid character.*") 32} 33 34func (s *RemoteSuite) TestFetchNonExistentEndpoint(c *C) { 35 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"ssh://non-existent/foo.git"}}) 36 err := r.Fetch(&FetchOptions{}) 37 c.Assert(err, NotNil) 38} 39 40func (s *RemoteSuite) TestFetchInvalidSchemaEndpoint(c *C) { 41 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"qux://foo"}}) 42 err := r.Fetch(&FetchOptions{}) 43 c.Assert(err, ErrorMatches, ".*unsupported scheme.*") 44} 45 46func (s *RemoteSuite) TestFetchInvalidFetchOptions(c *C) { 47 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"qux://foo"}}) 48 invalid := config.RefSpec("^*$ñ") 49 err := r.Fetch(&FetchOptions{RefSpecs: []config.RefSpec{invalid}}) 50 c.Assert(err, Equals, config.ErrRefSpecMalformedSeparator) 51} 52 53func (s *RemoteSuite) TestFetchWildcard(c *C) { 54 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 55 URLs: []string{s.GetBasicLocalRepositoryURL()}, 56 }) 57 58 s.testFetch(c, r, &FetchOptions{ 59 RefSpecs: []config.RefSpec{ 60 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 61 }, 62 }, []*plumbing.Reference{ 63 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 64 plumbing.NewReferenceFromStrings("refs/remotes/origin/branch", "e8d3ffab552895c19b9fcf7aa264d277cde33881"), 65 plumbing.NewReferenceFromStrings("refs/tags/v1.0.0", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 66 }) 67} 68 69func (s *RemoteSuite) TestFetchWildcardTags(c *C) { 70 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 71 URLs: []string{s.GetLocalRepositoryURL(fixtures.ByTag("tags").One())}, 72 }) 73 74 s.testFetch(c, r, &FetchOptions{ 75 RefSpecs: []config.RefSpec{ 76 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 77 }, 78 }, []*plumbing.Reference{ 79 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 80 plumbing.NewReferenceFromStrings("refs/tags/annotated-tag", "b742a2a9fa0afcfa9a6fad080980fbc26b007c69"), 81 plumbing.NewReferenceFromStrings("refs/tags/tree-tag", "152175bf7e5580299fa1f0ba41ef6474cc043b70"), 82 plumbing.NewReferenceFromStrings("refs/tags/commit-tag", "ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc"), 83 plumbing.NewReferenceFromStrings("refs/tags/blob-tag", "fe6cb94756faa81e5ed9240f9191b833db5f40ae"), 84 plumbing.NewReferenceFromStrings("refs/tags/lightweight-tag", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 85 }) 86} 87 88func (s *RemoteSuite) TestFetch(c *C) { 89 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 90 URLs: []string{s.GetLocalRepositoryURL(fixtures.ByTag("tags").One())}, 91 }) 92 93 s.testFetch(c, r, &FetchOptions{ 94 RefSpecs: []config.RefSpec{ 95 config.RefSpec("+refs/heads/master:refs/remotes/origin/master"), 96 }, 97 }, []*plumbing.Reference{ 98 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 99 }) 100} 101 102func (s *RemoteSuite) TestFetchContext(c *C) { 103 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 104 URLs: []string{s.GetLocalRepositoryURL(fixtures.ByTag("tags").One())}, 105 }) 106 107 ctx, cancel := context.WithCancel(context.Background()) 108 cancel() 109 110 err := r.FetchContext(ctx, &FetchOptions{ 111 RefSpecs: []config.RefSpec{ 112 config.RefSpec("+refs/heads/master:refs/remotes/origin/master"), 113 }, 114 }) 115 c.Assert(err, NotNil) 116} 117 118func (s *RemoteSuite) TestFetchWithAllTags(c *C) { 119 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 120 URLs: []string{s.GetLocalRepositoryURL(fixtures.ByTag("tags").One())}, 121 }) 122 123 s.testFetch(c, r, &FetchOptions{ 124 Tags: AllTags, 125 RefSpecs: []config.RefSpec{ 126 config.RefSpec("+refs/heads/master:refs/remotes/origin/master"), 127 }, 128 }, []*plumbing.Reference{ 129 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 130 plumbing.NewReferenceFromStrings("refs/tags/annotated-tag", "b742a2a9fa0afcfa9a6fad080980fbc26b007c69"), 131 plumbing.NewReferenceFromStrings("refs/tags/tree-tag", "152175bf7e5580299fa1f0ba41ef6474cc043b70"), 132 plumbing.NewReferenceFromStrings("refs/tags/commit-tag", "ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc"), 133 plumbing.NewReferenceFromStrings("refs/tags/blob-tag", "fe6cb94756faa81e5ed9240f9191b833db5f40ae"), 134 plumbing.NewReferenceFromStrings("refs/tags/lightweight-tag", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 135 }) 136} 137 138func (s *RemoteSuite) TestFetchWithNoTags(c *C) { 139 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 140 URLs: []string{s.GetLocalRepositoryURL(fixtures.ByTag("tags").One())}, 141 }) 142 143 s.testFetch(c, r, &FetchOptions{ 144 Tags: NoTags, 145 RefSpecs: []config.RefSpec{ 146 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 147 }, 148 }, []*plumbing.Reference{ 149 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "f7b877701fbf855b44c0a9e86f3fdce2c298b07f"), 150 }) 151 152} 153 154func (s *RemoteSuite) TestFetchWithDepth(c *C) { 155 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 156 URLs: []string{s.GetBasicLocalRepositoryURL()}, 157 }) 158 159 s.testFetch(c, r, &FetchOptions{ 160 Depth: 1, 161 RefSpecs: []config.RefSpec{ 162 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 163 }, 164 }, []*plumbing.Reference{ 165 plumbing.NewReferenceFromStrings("refs/remotes/origin/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 166 plumbing.NewReferenceFromStrings("refs/remotes/origin/branch", "e8d3ffab552895c19b9fcf7aa264d277cde33881"), 167 plumbing.NewReferenceFromStrings("refs/tags/v1.0.0", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 168 }) 169 170 c.Assert(r.s.(*memory.Storage).Objects, HasLen, 18) 171} 172 173func (s *RemoteSuite) testFetch(c *C, r *Remote, o *FetchOptions, expected []*plumbing.Reference) { 174 err := r.Fetch(o) 175 c.Assert(err, IsNil) 176 177 var refs int 178 l, err := r.s.IterReferences() 179 c.Assert(err, IsNil) 180 l.ForEach(func(r *plumbing.Reference) error { refs++; return nil }) 181 182 c.Assert(refs, Equals, len(expected)) 183 184 for _, exp := range expected { 185 r, err := r.s.Reference(exp.Name()) 186 c.Assert(err, IsNil) 187 c.Assert(exp.String(), Equals, r.String()) 188 } 189} 190 191func (s *RemoteSuite) TestFetchWithProgress(c *C) { 192 url := s.GetBasicLocalRepositoryURL() 193 sto := memory.NewStorage() 194 buf := bytes.NewBuffer(nil) 195 196 r := newRemote(sto, &config.RemoteConfig{Name: "foo", URLs: []string{url}}) 197 198 refspec := config.RefSpec("+refs/heads/*:refs/remotes/origin/*") 199 err := r.Fetch(&FetchOptions{ 200 RefSpecs: []config.RefSpec{refspec}, 201 Progress: buf, 202 }) 203 204 c.Assert(err, IsNil) 205 c.Assert(sto.Objects, HasLen, 31) 206 207 c.Assert(buf.Len(), Not(Equals), 0) 208} 209 210type mockPackfileWriter struct { 211 storage.Storer 212 PackfileWriterCalled bool 213} 214 215func (m *mockPackfileWriter) PackfileWriter() (io.WriteCloser, error) { 216 m.PackfileWriterCalled = true 217 return m.Storer.(storer.PackfileWriter).PackfileWriter() 218} 219 220func (s *RemoteSuite) TestFetchWithPackfileWriter(c *C) { 221 dir, err := ioutil.TempDir("", "fetch") 222 c.Assert(err, IsNil) 223 224 defer os.RemoveAll(dir) // clean up 225 226 fss, err := filesystem.NewStorage(osfs.New(dir)) 227 c.Assert(err, IsNil) 228 229 mock := &mockPackfileWriter{Storer: fss} 230 231 url := s.GetBasicLocalRepositoryURL() 232 r := newRemote(mock, &config.RemoteConfig{Name: "foo", URLs: []string{url}}) 233 234 refspec := config.RefSpec("+refs/heads/*:refs/remotes/origin/*") 235 err = r.Fetch(&FetchOptions{ 236 RefSpecs: []config.RefSpec{refspec}, 237 }) 238 239 c.Assert(err, IsNil) 240 241 var count int 242 iter, err := mock.IterEncodedObjects(plumbing.AnyObject) 243 c.Assert(err, IsNil) 244 245 iter.ForEach(func(plumbing.EncodedObject) error { 246 count++ 247 return nil 248 }) 249 250 c.Assert(count, Equals, 31) 251 c.Assert(mock.PackfileWriterCalled, Equals, true) 252} 253 254func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDate(c *C) { 255 url := s.GetBasicLocalRepositoryURL() 256 s.doTestFetchNoErrAlreadyUpToDate(c, url) 257} 258 259func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDateButStillUpdateLocalRemoteRefs(c *C) { 260 r := newRemote(memory.NewStorage(), &config.RemoteConfig{ 261 URLs: []string{s.GetBasicLocalRepositoryURL()}, 262 }) 263 264 o := &FetchOptions{ 265 RefSpecs: []config.RefSpec{ 266 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 267 }, 268 } 269 270 err := r.Fetch(o) 271 c.Assert(err, IsNil) 272 273 // Simulate an out of date remote ref even though we have the new commit locally 274 r.s.SetReference(plumbing.NewReferenceFromStrings( 275 "refs/remotes/origin/master", "918c48b83bd081e863dbe1b80f8998f058cd8294", 276 )) 277 278 err = r.Fetch(o) 279 c.Assert(err, IsNil) 280 281 exp := plumbing.NewReferenceFromStrings( 282 "refs/remotes/origin/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5", 283 ) 284 285 ref, err := r.s.Reference("refs/remotes/origin/master") 286 c.Assert(err, IsNil) 287 c.Assert(exp.String(), Equals, ref.String()) 288} 289 290func (s *RemoteSuite) TestFetchNoErrAlreadyUpToDateWithNonCommitObjects(c *C) { 291 fixture := fixtures.ByTag("tags").One() 292 url := s.GetLocalRepositoryURL(fixture) 293 s.doTestFetchNoErrAlreadyUpToDate(c, url) 294} 295 296func (s *RemoteSuite) doTestFetchNoErrAlreadyUpToDate(c *C, url string) { 297 r := newRemote(memory.NewStorage(), &config.RemoteConfig{URLs: []string{url}}) 298 299 o := &FetchOptions{ 300 RefSpecs: []config.RefSpec{ 301 config.RefSpec("+refs/heads/*:refs/remotes/origin/*"), 302 }, 303 } 304 305 err := r.Fetch(o) 306 c.Assert(err, IsNil) 307 err = r.Fetch(o) 308 c.Assert(err, Equals, NoErrAlreadyUpToDate) 309} 310 311func (s *RemoteSuite) testFetchFastForward(c *C, sto storage.Storer) { 312 r := newRemote(sto, &config.RemoteConfig{ 313 URLs: []string{s.GetBasicLocalRepositoryURL()}, 314 }) 315 316 s.testFetch(c, r, &FetchOptions{ 317 RefSpecs: []config.RefSpec{ 318 config.RefSpec("+refs/heads/master:refs/heads/master"), 319 }, 320 }, []*plumbing.Reference{ 321 plumbing.NewReferenceFromStrings("refs/heads/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 322 }) 323 324 // First make sure that we error correctly when a force is required. 325 err := r.Fetch(&FetchOptions{ 326 RefSpecs: []config.RefSpec{ 327 config.RefSpec("refs/heads/branch:refs/heads/master"), 328 }, 329 }) 330 c.Assert(err, Equals, ErrForceNeeded) 331 332 // And that forcing it fixes the problem. 333 err = r.Fetch(&FetchOptions{ 334 RefSpecs: []config.RefSpec{ 335 config.RefSpec("+refs/heads/branch:refs/heads/master"), 336 }, 337 }) 338 c.Assert(err, IsNil) 339 340 // Now test that a fast-forward, non-force fetch works. 341 r.s.SetReference(plumbing.NewReferenceFromStrings( 342 "refs/heads/master", "918c48b83bd081e863dbe1b80f8998f058cd8294", 343 )) 344 s.testFetch(c, r, &FetchOptions{ 345 RefSpecs: []config.RefSpec{ 346 config.RefSpec("refs/heads/master:refs/heads/master"), 347 }, 348 }, []*plumbing.Reference{ 349 plumbing.NewReferenceFromStrings("refs/heads/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 350 }) 351} 352 353func (s *RemoteSuite) TestFetchFastForwardMem(c *C) { 354 s.testFetchFastForward(c, memory.NewStorage()) 355} 356 357func (s *RemoteSuite) TestFetchFastForwardFS(c *C) { 358 dir, err := ioutil.TempDir("", "fetch") 359 c.Assert(err, IsNil) 360 361 defer os.RemoveAll(dir) // clean up 362 363 fss, err := filesystem.NewStorage(osfs.New(dir)) 364 c.Assert(err, IsNil) 365 366 // This exercises `storage.filesystem.Storage.CheckAndSetReference()`. 367 s.testFetchFastForward(c, fss) 368} 369 370func (s *RemoteSuite) TestString(c *C) { 371 r := newRemote(nil, &config.RemoteConfig{ 372 Name: "foo", 373 URLs: []string{"https://github.com/git-fixtures/basic.git"}, 374 }) 375 376 c.Assert(r.String(), Equals, ""+ 377 "foo\thttps://github.com/git-fixtures/basic.git (fetch)\n"+ 378 "foo\thttps://github.com/git-fixtures/basic.git (push)", 379 ) 380} 381 382func (s *RemoteSuite) TestPushToEmptyRepository(c *C) { 383 url := c.MkDir() 384 server, err := PlainInit(url, true) 385 c.Assert(err, IsNil) 386 387 srcFs := fixtures.Basic().One().DotGit() 388 sto, err := filesystem.NewStorage(srcFs) 389 c.Assert(err, IsNil) 390 391 r := newRemote(sto, &config.RemoteConfig{ 392 Name: DefaultRemoteName, 393 URLs: []string{url}, 394 }) 395 396 rs := config.RefSpec("refs/heads/*:refs/heads/*") 397 err = r.Push(&PushOptions{ 398 RefSpecs: []config.RefSpec{rs}, 399 }) 400 c.Assert(err, IsNil) 401 402 iter, err := r.s.IterReferences() 403 c.Assert(err, IsNil) 404 405 expected := make(map[string]string) 406 iter.ForEach(func(ref *plumbing.Reference) error { 407 if !ref.Name().IsBranch() { 408 return nil 409 } 410 411 expected[ref.Name().String()] = ref.Hash().String() 412 return nil 413 }) 414 c.Assert(err, IsNil) 415 416 AssertReferences(c, server, expected) 417 418} 419 420func (s *RemoteSuite) TestPushContext(c *C) { 421 url := c.MkDir() 422 _, err := PlainInit(url, true) 423 c.Assert(err, IsNil) 424 425 fs := fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().DotGit() 426 sto, err := filesystem.NewStorage(fs) 427 c.Assert(err, IsNil) 428 429 r := newRemote(sto, &config.RemoteConfig{ 430 Name: DefaultRemoteName, 431 URLs: []string{url}, 432 }) 433 434 ctx, cancel := context.WithCancel(context.Background()) 435 cancel() 436 437 err = r.PushContext(ctx, &PushOptions{ 438 RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"}, 439 }) 440 c.Assert(err, NotNil) 441} 442 443func (s *RemoteSuite) TestPushTags(c *C) { 444 url := c.MkDir() 445 server, err := PlainInit(url, true) 446 c.Assert(err, IsNil) 447 448 fs := fixtures.ByURL("https://github.com/git-fixtures/tags.git").One().DotGit() 449 sto, err := filesystem.NewStorage(fs) 450 c.Assert(err, IsNil) 451 452 r := newRemote(sto, &config.RemoteConfig{ 453 Name: DefaultRemoteName, 454 URLs: []string{url}, 455 }) 456 457 err = r.Push(&PushOptions{ 458 RefSpecs: []config.RefSpec{"refs/tags/*:refs/tags/*"}, 459 }) 460 c.Assert(err, IsNil) 461 462 AssertReferences(c, server, map[string]string{ 463 "refs/tags/lightweight-tag": "f7b877701fbf855b44c0a9e86f3fdce2c298b07f", 464 "refs/tags/annotated-tag": "b742a2a9fa0afcfa9a6fad080980fbc26b007c69", 465 "refs/tags/commit-tag": "ad7897c0fb8e7d9a9ba41fa66072cf06095a6cfc", 466 "refs/tags/blob-tag": "fe6cb94756faa81e5ed9240f9191b833db5f40ae", 467 "refs/tags/tree-tag": "152175bf7e5580299fa1f0ba41ef6474cc043b70", 468 }) 469} 470 471func (s *RemoteSuite) TestPushNoErrAlreadyUpToDate(c *C) { 472 fs := fixtures.Basic().One().DotGit() 473 sto, err := filesystem.NewStorage(fs) 474 c.Assert(err, IsNil) 475 476 r := newRemote(sto, &config.RemoteConfig{ 477 Name: DefaultRemoteName, 478 URLs: []string{fs.Root()}, 479 }) 480 481 err = r.Push(&PushOptions{ 482 RefSpecs: []config.RefSpec{"refs/heads/*:refs/heads/*"}, 483 }) 484 c.Assert(err, Equals, NoErrAlreadyUpToDate) 485} 486 487func (s *RemoteSuite) TestPushDeleteReference(c *C) { 488 fs := fixtures.Basic().One().DotGit() 489 sto, err := filesystem.NewStorage(fs) 490 c.Assert(err, IsNil) 491 492 r, err := PlainClone(c.MkDir(), true, &CloneOptions{ 493 URL: fs.Root(), 494 }) 495 c.Assert(err, IsNil) 496 497 remote, err := r.Remote(DefaultRemoteName) 498 c.Assert(err, IsNil) 499 500 err = remote.Push(&PushOptions{ 501 RefSpecs: []config.RefSpec{":refs/heads/branch"}, 502 }) 503 c.Assert(err, IsNil) 504 505 _, err = sto.Reference(plumbing.ReferenceName("refs/heads/branch")) 506 c.Assert(err, Equals, plumbing.ErrReferenceNotFound) 507 508 _, err = r.Storer.Reference(plumbing.ReferenceName("refs/heads/branch")) 509 c.Assert(err, Equals, plumbing.ErrReferenceNotFound) 510} 511 512func (s *RemoteSuite) TestPushRejectNonFastForward(c *C) { 513 fs := fixtures.Basic().One().DotGit() 514 server, err := filesystem.NewStorage(fs) 515 c.Assert(err, IsNil) 516 517 r, err := PlainClone(c.MkDir(), true, &CloneOptions{ 518 URL: fs.Root(), 519 }) 520 c.Assert(err, IsNil) 521 522 remote, err := r.Remote(DefaultRemoteName) 523 c.Assert(err, IsNil) 524 525 branch := plumbing.ReferenceName("refs/heads/branch") 526 oldRef, err := server.Reference(branch) 527 c.Assert(err, IsNil) 528 c.Assert(oldRef, NotNil) 529 530 err = remote.Push(&PushOptions{RefSpecs: []config.RefSpec{ 531 "refs/heads/master:refs/heads/branch", 532 }}) 533 c.Assert(err, ErrorMatches, "non-fast-forward update: refs/heads/branch") 534 535 newRef, err := server.Reference(branch) 536 c.Assert(err, IsNil) 537 c.Assert(newRef, DeepEquals, oldRef) 538} 539 540func (s *RemoteSuite) TestPushForce(c *C) { 541 f := fixtures.Basic().One() 542 sto, err := filesystem.NewStorage(f.DotGit()) 543 c.Assert(err, IsNil) 544 545 dstFs := f.DotGit() 546 dstSto, err := filesystem.NewStorage(dstFs) 547 c.Assert(err, IsNil) 548 549 url := dstFs.Root() 550 r := newRemote(sto, &config.RemoteConfig{ 551 Name: DefaultRemoteName, 552 URLs: []string{url}, 553 }) 554 555 oldRef, err := dstSto.Reference(plumbing.ReferenceName("refs/heads/branch")) 556 c.Assert(err, IsNil) 557 c.Assert(oldRef, NotNil) 558 559 err = r.Push(&PushOptions{RefSpecs: []config.RefSpec{ 560 config.RefSpec("+refs/heads/master:refs/heads/branch"), 561 }}) 562 c.Assert(err, IsNil) 563 564 newRef, err := dstSto.Reference(plumbing.ReferenceName("refs/heads/branch")) 565 c.Assert(err, IsNil) 566 c.Assert(newRef, Not(DeepEquals), oldRef) 567} 568 569func (s *RemoteSuite) TestPushNewReference(c *C) { 570 fs := fixtures.Basic().One().DotGit() 571 url := c.MkDir() 572 server, err := PlainClone(url, true, &CloneOptions{ 573 URL: fs.Root(), 574 }) 575 c.Assert(err, IsNil) 576 577 r, err := PlainClone(c.MkDir(), true, &CloneOptions{ 578 URL: url, 579 }) 580 c.Assert(err, IsNil) 581 582 remote, err := r.Remote(DefaultRemoteName) 583 c.Assert(err, IsNil) 584 585 ref, err := r.Reference(plumbing.ReferenceName("refs/heads/master"), true) 586 c.Assert(err, IsNil) 587 588 err = remote.Push(&PushOptions{RefSpecs: []config.RefSpec{ 589 "refs/heads/master:refs/heads/branch2", 590 }}) 591 c.Assert(err, IsNil) 592 593 AssertReferences(c, server, map[string]string{ 594 "refs/heads/branch2": ref.Hash().String(), 595 }) 596 597 AssertReferences(c, r, map[string]string{ 598 "refs/remotes/origin/branch2": ref.Hash().String(), 599 }) 600} 601 602func (s *RemoteSuite) TestPushNewReferenceAndDeleteInBatch(c *C) { 603 fs := fixtures.Basic().One().DotGit() 604 url := c.MkDir() 605 server, err := PlainClone(url, true, &CloneOptions{ 606 URL: fs.Root(), 607 }) 608 c.Assert(err, IsNil) 609 610 r, err := PlainClone(c.MkDir(), true, &CloneOptions{ 611 URL: url, 612 }) 613 c.Assert(err, IsNil) 614 615 remote, err := r.Remote(DefaultRemoteName) 616 c.Assert(err, IsNil) 617 618 ref, err := r.Reference(plumbing.ReferenceName("refs/heads/master"), true) 619 c.Assert(err, IsNil) 620 621 err = remote.Push(&PushOptions{RefSpecs: []config.RefSpec{ 622 "refs/heads/master:refs/heads/branch2", 623 ":refs/heads/branch", 624 }}) 625 c.Assert(err, IsNil) 626 627 AssertReferences(c, server, map[string]string{ 628 "refs/heads/branch2": ref.Hash().String(), 629 }) 630 631 AssertReferences(c, r, map[string]string{ 632 "refs/remotes/origin/branch2": ref.Hash().String(), 633 }) 634 635 _, err = server.Storer.Reference(plumbing.ReferenceName("refs/heads/branch")) 636 c.Assert(err, Equals, plumbing.ErrReferenceNotFound) 637} 638 639func (s *RemoteSuite) TestPushInvalidEndpoint(c *C) { 640 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"http://\\"}}) 641 err := r.Push(&PushOptions{RemoteName: "foo"}) 642 c.Assert(err, ErrorMatches, ".*invalid character.*") 643} 644 645func (s *RemoteSuite) TestPushNonExistentEndpoint(c *C) { 646 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"ssh://non-existent/foo.git"}}) 647 err := r.Push(&PushOptions{}) 648 c.Assert(err, NotNil) 649} 650 651func (s *RemoteSuite) TestPushInvalidSchemaEndpoint(c *C) { 652 r := newRemote(nil, &config.RemoteConfig{Name: "origin", URLs: []string{"qux://foo"}}) 653 err := r.Push(&PushOptions{}) 654 c.Assert(err, ErrorMatches, ".*unsupported scheme.*") 655} 656 657func (s *RemoteSuite) TestPushInvalidFetchOptions(c *C) { 658 r := newRemote(nil, &config.RemoteConfig{Name: "foo", URLs: []string{"qux://foo"}}) 659 invalid := config.RefSpec("^*$ñ") 660 err := r.Push(&PushOptions{RefSpecs: []config.RefSpec{invalid}}) 661 c.Assert(err, Equals, config.ErrRefSpecMalformedSeparator) 662} 663 664func (s *RemoteSuite) TestPushInvalidRefSpec(c *C) { 665 r := newRemote(nil, &config.RemoteConfig{ 666 Name: DefaultRemoteName, 667 URLs: []string{"some-url"}, 668 }) 669 670 rs := config.RefSpec("^*$**") 671 err := r.Push(&PushOptions{ 672 RefSpecs: []config.RefSpec{rs}, 673 }) 674 c.Assert(err, Equals, config.ErrRefSpecMalformedSeparator) 675} 676 677func (s *RemoteSuite) TestPushWrongRemoteName(c *C) { 678 r := newRemote(nil, &config.RemoteConfig{ 679 Name: DefaultRemoteName, 680 URLs: []string{"some-url"}, 681 }) 682 683 err := r.Push(&PushOptions{ 684 RemoteName: "other-remote", 685 }) 686 c.Assert(err, ErrorMatches, ".*remote names don't match.*") 687} 688 689func (s *RemoteSuite) TestGetHaves(c *C) { 690 f := fixtures.Basic().One() 691 sto, err := filesystem.NewStorage(f.DotGit()) 692 c.Assert(err, IsNil) 693 694 var localRefs = []*plumbing.Reference{ 695 plumbing.NewReferenceFromStrings( 696 "foo", 697 "f7b877701fbf855b44c0a9e86f3fdce2c298b07f", 698 ), 699 plumbing.NewReferenceFromStrings( 700 "bar", 701 "fe6cb94756faa81e5ed9240f9191b833db5f40ae", 702 ), 703 plumbing.NewReferenceFromStrings( 704 "qux", 705 "f7b877701fbf855b44c0a9e86f3fdce2c298b07f", 706 ), 707 } 708 709 l, err := getHaves(localRefs, memory.NewStorage(), sto) 710 c.Assert(err, IsNil) 711 c.Assert(l, HasLen, 2) 712} 713 714func (s *RemoteSuite) TestList(c *C) { 715 repo := fixtures.Basic().One() 716 remote := newRemote(memory.NewStorage(), &config.RemoteConfig{ 717 Name: DefaultRemoteName, 718 URLs: []string{repo.URL}, 719 }) 720 721 refs, err := remote.List(&ListOptions{}) 722 c.Assert(err, IsNil) 723 724 expected := []*plumbing.Reference{ 725 plumbing.NewSymbolicReference("HEAD", "refs/heads/master"), 726 plumbing.NewReferenceFromStrings("refs/heads/master", "6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), 727 plumbing.NewReferenceFromStrings("refs/heads/branch", "e8d3ffab552895c19b9fcf7aa264d277cde33881"), 728 plumbing.NewReferenceFromStrings("refs/pull/1/head", "b8e471f58bcbca63b07bda20e428190409c2db47"), 729 plumbing.NewReferenceFromStrings("refs/pull/2/head", "9632f02833b2f9613afb5e75682132b0b22e4a31"), 730 plumbing.NewReferenceFromStrings("refs/pull/2/merge", "c37f58a130ca555e42ff96a071cb9ccb3f437504"), 731 } 732 c.Assert(len(refs), Equals, len(expected)) 733 for _, e := range expected { 734 found := false 735 for _, r := range refs { 736 if r.Name() == e.Name() { 737 found = true 738 c.Assert(r, DeepEquals, e) 739 } 740 } 741 c.Assert(found, Equals, true) 742 } 743}