@@ -32,6 +32,7 @@ import (
32
32
"time"
33
33
34
34
extgogit "github.com/fluxcd/go-git/v5"
35
+ "github.com/fluxcd/go-git/v5/config"
35
36
"github.com/fluxcd/go-git/v5/plumbing"
36
37
"github.com/fluxcd/go-git/v5/plumbing/cache"
37
38
"github.com/fluxcd/go-git/v5/plumbing/object"
@@ -493,6 +494,147 @@ func TestClone_cloneSemVer(t *testing.T) {
493
494
}
494
495
}
495
496
497
+ func TestClone_cloneRefName (t * testing.T ) {
498
+ g := NewWithT (t )
499
+
500
+ server , err := gittestserver .NewTempGitServer ()
501
+ g .Expect (err ).ToNot (HaveOccurred ())
502
+ defer os .RemoveAll (server .Root ())
503
+ err = server .StartHTTP ()
504
+ g .Expect (err ).ToNot (HaveOccurred ())
505
+ defer server .StopHTTP ()
506
+
507
+ repoPath := "test.git"
508
+ err = server .InitRepo ("../testdata/git/repo" , git .DefaultBranch , repoPath )
509
+ g .Expect (err ).ToNot (HaveOccurred ())
510
+ repoURL := server .HTTPAddress () + "/" + repoPath
511
+ repo , err := extgogit .PlainClone (t .TempDir (), false , & extgogit.CloneOptions {
512
+ URL : repoURL ,
513
+ })
514
+ g .Expect (err ).ToNot (HaveOccurred ())
515
+
516
+ // head is the current HEAD on master
517
+ head , err := repo .Head ()
518
+ g .Expect (err ).ToNot (HaveOccurred ())
519
+ err = createBranch (repo , "test" )
520
+ g .Expect (err ).ToNot (HaveOccurred ())
521
+ err = repo .Push (& extgogit.PushOptions {})
522
+ g .Expect (err ).ToNot (HaveOccurred ())
523
+
524
+ // create a new branch for testing tags in order to avoid disturbing the state
525
+ // of the current branch that's used for testing branches later.
526
+ err = createBranch (repo , "tag-testing" )
527
+ g .Expect (err ).ToNot (HaveOccurred ())
528
+ hash , err := commitFile (repo , "bar.txt" , "this is the way" , time .Now ())
529
+ g .Expect (err ).ToNot (HaveOccurred ())
530
+ err = repo .Push (& extgogit.PushOptions {})
531
+ g .Expect (err ).ToNot (HaveOccurred ())
532
+ _ , err = tag (repo , hash , false , "v0.1.0" , time .Now ())
533
+ g .Expect (err ).ToNot (HaveOccurred ())
534
+ err = repo .Push (& extgogit.PushOptions {
535
+ RefSpecs : []config.RefSpec {
536
+ config .RefSpec ("+refs/tags/v0.1.0" + ":refs/tags/v0.1.0" ),
537
+ },
538
+ })
539
+ g .Expect (err ).ToNot (HaveOccurred ())
540
+
541
+ // set a custom reference, in the format of GitHub PRs.
542
+ err = repo .Storer .SetReference (plumbing .NewHashReference (plumbing .ReferenceName ("/refs/pull/1/head" ), hash ))
543
+ g .Expect (err ).ToNot (HaveOccurred ())
544
+ err = repo .Push (& extgogit.PushOptions {
545
+ RefSpecs : []config.RefSpec {
546
+ config .RefSpec ("+refs/pull/1/head" + ":refs/pull/1/head" ),
547
+ },
548
+ })
549
+ g .Expect (err ).ToNot (HaveOccurred ())
550
+
551
+ tests := []struct {
552
+ name string
553
+ refName string
554
+ filesCreated map [string ]string
555
+ lastRevision string
556
+ expectedCommit string
557
+ expectedConcreteCommit bool
558
+ expectedErr string
559
+ }{
560
+ {
561
+ name : "ref name pointing to a branch" ,
562
+ refName : "refs/heads/master" ,
563
+ filesCreated : map [string ]string {"foo.txt" : "test file\n " },
564
+ expectedCommit : git .Hash (head .Hash ().String ()).Digest (),
565
+ expectedConcreteCommit : true ,
566
+ },
567
+ {
568
+ name : "skip clone if LastRevision is unchanged" ,
569
+ refName : "refs/heads/master" ,
570
+ lastRevision : git .Hash (head .Hash ().String ()).Digest (),
571
+ expectedCommit : git .Hash (head .Hash ().String ()).Digest (),
572
+ expectedConcreteCommit : false ,
573
+ },
574
+ {
575
+ name : "skip clone if LastRevision is unchanged even if the reference changes" ,
576
+ refName : "refs/heads/test" ,
577
+ lastRevision : git .Hash (head .Hash ().String ()).Digest (),
578
+ expectedCommit : git .Hash (head .Hash ().String ()).Digest (),
579
+ expectedConcreteCommit : false ,
580
+ },
581
+ {
582
+ name : "ref name pointing to a tag" ,
583
+ refName : "refs/tags/v0.1.0" ,
584
+ filesCreated : map [string ]string {"bar.txt" : "this is the way" },
585
+ lastRevision : git .Hash (head .Hash ().String ()).Digest (),
586
+ expectedCommit : git .Hash (hash .String ()).Digest (),
587
+ expectedConcreteCommit : true ,
588
+ },
589
+ {
590
+ name : "ref name pointing to a pull request" ,
591
+ refName : "refs/pull/1/head" ,
592
+ filesCreated : map [string ]string {"bar.txt" : "this is the way" },
593
+ expectedCommit : git .Hash (hash .String ()).Digest (),
594
+ expectedConcreteCommit : true ,
595
+ },
596
+ {
597
+ name : "non existing ref" ,
598
+ refName : "refs/tags/v0.2.0" ,
599
+ expectedErr : "unable to resolve ref 'refs/tags/v0.2.0' to a specific commit" ,
600
+ },
601
+ }
602
+
603
+ for _ , tt := range tests {
604
+ t .Run (tt .name , func (t * testing.T ) {
605
+ g := NewWithT (t )
606
+ tmpDir := t .TempDir ()
607
+ ggc , err := NewClient (tmpDir , & git.AuthOptions {Transport : git .HTTP })
608
+ g .Expect (err ).ToNot (HaveOccurred ())
609
+
610
+ cc , err := ggc .Clone (context .TODO (), repoURL , repository.CloneOptions {
611
+ CheckoutStrategy : repository.CheckoutStrategy {
612
+ RefName : tt .refName ,
613
+ },
614
+ LastObservedCommit : tt .lastRevision ,
615
+ })
616
+
617
+ if tt .expectedErr != "" {
618
+ g .Expect (err ).To (HaveOccurred ())
619
+ g .Expect (err .Error ()).To (ContainSubstring (tt .expectedErr ))
620
+ g .Expect (cc ).To (BeNil ())
621
+ return
622
+ }
623
+
624
+ g .Expect (err ).ToNot (HaveOccurred ())
625
+ g .Expect (cc .String ()).To (Equal (tt .expectedCommit ))
626
+ g .Expect (git .IsConcreteCommit (* cc )).To (Equal (tt .expectedConcreteCommit ))
627
+
628
+ for k , v := range tt .filesCreated {
629
+ g .Expect (filepath .Join (tmpDir , k )).To (BeARegularFile ())
630
+ content , err := os .ReadFile (filepath .Join (tmpDir , k ))
631
+ g .Expect (err ).ToNot (HaveOccurred ())
632
+ g .Expect (string (content )).To (Equal (v ))
633
+ }
634
+ })
635
+ }
636
+ }
637
+
496
638
func Test_cloneSubmodule (t * testing.T ) {
497
639
g := NewWithT (t )
498
640
@@ -997,6 +1139,16 @@ func Test_getRemoteHEAD(t *testing.T) {
997
1139
head , err = getRemoteHEAD (context .TODO (), path , ref , & git.AuthOptions {}, nil )
998
1140
g .Expect (err ).ToNot (HaveOccurred ())
999
1141
g .Expect (head ).To (Equal (fmt .Sprintf ("%s@%s" , "v0.1.0" , git .Hash (cc .String ()).Digest ())))
1142
+
1143
+ ref = plumbing .ReferenceName ("/refs/heads/main" )
1144
+ head , err = getRemoteHEAD (context .TODO (), path , ref , & git.AuthOptions {}, nil )
1145
+ g .Expect (err ).To (HaveOccurred ())
1146
+ g .Expect (err .Error ()).To (Equal (fmt .Sprintf ("ref %s is invalid; Git refs cannot begin or end with a slash '/'" , ref .String ())))
1147
+
1148
+ ref = plumbing .ReferenceName ("refs/heads/main/" )
1149
+ head , err = getRemoteHEAD (context .TODO (), path , ref , & git.AuthOptions {}, nil )
1150
+ g .Expect (err ).To (HaveOccurred ())
1151
+ g .Expect (err .Error ()).To (Equal (fmt .Sprintf ("ref %s is invalid; Git refs cannot begin or end with a slash '/'" , ref .String ())))
1000
1152
}
1001
1153
1002
1154
func TestClone_CredentialsOverHttp (t * testing.T ) {
0 commit comments