github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/checkout_test.go (about) 1 package git 2 3 import ( 4 "io/ioutil" 5 "os" 6 "testing" 7 "fmt" 8 ) 9 10 // TestCheckoutBranch tests that variations of "git checkout branchname" works 11 // as expected. 12 func TestCheckoutBranch(t *testing.T) { 13 if os.Getenv("SkipKnownFailures") == "true" { 14 // No global .gitconfig file exists error 15 // happens in a clean environment where 16 // name/email aren't set up. 17 fmt.Printf("Skipping known failure under CI") 18 return 19 } 20 dir, err := ioutil.TempDir("", "gitcommit") 21 if err != nil { 22 t.Fatal(err) 23 } 24 defer os.RemoveAll(dir) 25 26 // Init a repo to test an initial commit in. 27 c, err := Init(nil, InitOptions{Quiet: true}, dir) 28 if err != nil { 29 t.Fatal(err) 30 } 31 if err := os.Chdir(dir); err != nil { 32 t.Fatal(err) 33 } 34 if err := ioutil.WriteFile(dir+"/foo.txt", []byte("foo\n"), 0644); err != nil { 35 t.Fatal(err) 36 } 37 if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil { 38 t.Fatal(err) 39 } 40 initialCmt, err := Commit(c, CommitOptions{}, "Initial commit", nil) 41 if err != nil { 42 t.Fatal(err) 43 } 44 45 // Create a branch and check it out. 46 if err := c.CreateBranch("notmaster", initialCmt); err != nil { 47 t.Fatal(err) 48 } 49 if err := Checkout(c, CheckoutOptions{}, "notmaster", nil); err != nil { 50 t.Fatal(err) 51 } 52 53 if err := ioutil.WriteFile(dir+"/foo.txt", []byte("bar\n"), 0644); err != nil { 54 t.Fatal(err) 55 } 56 if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil { 57 t.Fatal(err) 58 } 59 // commit to the branch so that our branches are in different states. 60 notmasterCmt, err := Commit(c, CommitOptions{}, "notmaster", nil) 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 mastercrev, err := RevParseCommitish(c, &RevParseOptions{}, "master") 66 if err != nil { 67 t.Fatal(err) 68 } 69 masterc, err := mastercrev.CommitID(c) 70 71 notmasterrev, err := RevParseCommitish(c, &RevParseOptions{}, "notmaster") 72 if err != nil { 73 t.Fatal(err) 74 } 75 notmasterc, err := notmasterrev.CommitID(c) 76 if err != nil { 77 t.Fatal(err) 78 } 79 80 if masterc != initialCmt || notmasterc != notmasterCmt { 81 t.Fatal("RevParse did not return the correct branch commit.") 82 } 83 84 head, err := SymbolicRefGet(c, SymbolicRefOptions{}, "HEAD") 85 if err != nil { 86 t.Fatal("Could not get HEAD reference") 87 } 88 if head != RefSpec("refs/heads/notmaster") { 89 t.Errorf("Checkout branch variation did not change head reference. Got: %v", head) 90 } 91 92 // Go back to the master branch with a clean working tree 93 if err := Checkout(c, CheckoutOptions{}, "master", nil); err != nil { 94 t.Fatal(err) 95 } 96 head, err = SymbolicRefGet(c, SymbolicRefOptions{}, "HEAD") 97 if err != nil { 98 t.Fatal("Could not get HEAD reference") 99 } 100 if head != RefSpec("refs/heads/master") { 101 t.Errorf("Checkout branch variation did not change head reference. Got: %v", head) 102 } 103 104 foo, err := ioutil.ReadFile("foo.txt") 105 if err != nil { 106 t.Fatal(err) 107 } 108 if string(foo) != "foo\n" { 109 t.Errorf("Incorrect content in foo. Expected foo\n, got %v", string(foo)) 110 } 111 112 // Go back to notmaster with a dirty working tree. This should fail 113 if err := ioutil.WriteFile(dir+"/foo.txt", []byte("baz\n"), 0644); err != nil { 114 t.Fatal(err) 115 } 116 if err := Checkout(c, CheckoutOptions{}, "notmaster", nil); err == nil { 117 t.Error("Expected failed checkout due to unmerged changes, got no error") 118 } 119 foo, err = ioutil.ReadFile("foo.txt") 120 if err != nil { 121 t.Fatal(err) 122 } 123 if string(foo) != "baz\n" { 124 t.Errorf("File was modified by unfinished checkout.") 125 } 126 if err := Checkout(c, CheckoutOptions{Force: true}, "notmaster", nil); err != nil { 127 t.Errorf("Could not force checkout: %v", err) 128 } 129 foo, err = ioutil.ReadFile("foo.txt") 130 if err != nil { 131 t.Fatal(err) 132 } 133 if string(foo) != "bar\n" { 134 t.Errorf("File was not modified in forced checkout. Got %v want %v", string(foo), "bar") 135 } 136 if err := Checkout(c, CheckoutOptions{Detach: true}, "master", nil); err != nil { 137 t.Errorf("Error detaching checkout: %v", err) 138 } 139 foo, err = ioutil.ReadFile("foo.txt") 140 if err != nil { 141 t.Fatal(err) 142 } 143 if string(foo) != "foo\n" { 144 t.Errorf("File was not modified in detached checkout. Got %v want %v", string(foo), "foo") 145 } 146 147 headfile, err := ioutil.ReadFile(c.GitDir.String() + "/HEAD") 148 if err != nil { 149 t.Fatal(err) 150 } 151 152 if expected := masterc.String(); string(headfile) != expected { 153 t.Errorf("Head was not correctly modified by checkout --detach. Got %s want %s", string(headfile), expected) 154 } 155 156 // Since we're in a detached head state, test that we can get back 157 // to a normal state by checkouting master 158 if err := Checkout(c, CheckoutOptions{}, "master", nil); err != nil { 159 t.Fatal(err) 160 } 161 head, err = SymbolicRefGet(c, SymbolicRefOptions{}, "HEAD") 162 if err != nil { 163 t.Fatal("Could not get HEAD reference") 164 } 165 if head != RefSpec("refs/heads/master") { 166 t.Errorf("Checkout branch variation did not change head from detached head mode. Got: %v", head) 167 } 168 }