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  }