github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/apply_test.go (about)

     1  package git
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"testing"
     7  )
     8  
     9  // TestApply tests that the basic usage of the "Apply" command works
    10  // as expected and is atomic for the unified diff format.
    11  func TestUnidiffApply(t *testing.T) {
    12  	dir, err := ioutil.TempDir("", "gitapply")
    13  	if err != nil {
    14  		t.Fatal(err)
    15  	}
    16  	defer os.RemoveAll(dir)
    17  
    18  	// Init a repo to test an initial commit in.
    19  	c, err := Init(nil, InitOptions{Quiet: true}, dir)
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	if err := os.Chdir(dir); err != nil {
    24  		t.Fatal(err)
    25  	}
    26  	if err := ioutil.WriteFile(dir+"/foo.txt", []byte("foo\n"), 0644); err != nil {
    27  		t.Fatal(err)
    28  	}
    29  
    30  	patch, err := ioutil.TempFile("", "applytestpatch")
    31  	if err != nil {
    32  		t.Fatal(err)
    33  	}
    34  	defer os.Remove(patch.Name())
    35  	if err := ioutil.WriteFile(patch.Name(), []byte(
    36  		`diff --git a/foo.txt b/foo.txt
    37  --- a/foo.txt
    38  +++ b/foo.txt
    39  @@ -1 +1 @@
    40  -foo
    41  +bar
    42  `), 0644); err != nil {
    43  		t.Fatal(err)
    44  	}
    45  
    46  	if err := Apply(c, ApplyOptions{}, []File{File(patch.Name())}); err != nil {
    47  		t.Fatalf("Error with basic git apply: %v", err)
    48  	}
    49  
    50  	file, err := ioutil.ReadFile("foo.txt")
    51  	if err != nil {
    52  		t.Fatal(err)
    53  	}
    54  
    55  	if got := string(file); got != "bar\n" {
    56  		t.Fatalf("Unexpected value of foo.txt after simple patch: got %v want %v", got, "bar\n")
    57  	}
    58  
    59  	// Make it an invalid patch. (The content of foo.txt is currently "bar\n", not "foo\n")
    60  	if err := ioutil.WriteFile(patch.Name(), []byte(
    61  		`diff --git a/foo.txt b/foo.txt
    62  --- a/foo.txt
    63  +++ b/foo.txt
    64  @@ -1 +1 @@
    65  -foo
    66  +barr
    67  `), 0644); err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	if err := Apply(c, ApplyOptions{}, []File{File(patch.Name())}); err == nil {
    71  		t.Fatal("Expected error with invalid patch, got none.")
    72  	}
    73  
    74  	file, err = ioutil.ReadFile("foo.txt")
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  
    79  	if got := string(file); got != "bar\n" {
    80  		t.Fatalf("Unexpected value of foo.txt after invalid patch: got %v want %v", got, "bar\n")
    81  	}
    82  
    83  	// Now ensure that the changes are atomic. If they're not, bar.txt will
    84  	// be modified but foo.txt will fail.
    85  	if err := ioutil.WriteFile(dir+"/foo.txt", []byte("foo\n"), 0644); err != nil {
    86  		t.Fatal(err)
    87  	}
    88  
    89  	if err := ioutil.WriteFile(dir+"/bar.txt", []byte("bar\n"), 0644); err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	if err := ioutil.WriteFile(patch.Name(), []byte(
    93  		`diff --git a/bar.txt b/bar.txt
    94  --- a/bar.txt
    95  +++ b/bar.txt
    96  @@ -1 +1 @@
    97  -bar
    98  +qux
    99  
   100  diff --git a/foo.txt b/foo.txt
   101  --- a/foo.txt
   102  +++ b/foo.txt
   103  @@ -1 +1 @@
   104  -foob
   105  +barr
   106  `), 0644); err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	if err := Apply(c, ApplyOptions{}, []File{File(patch.Name())}); err == nil {
   110  		t.Fatal("Expected error with invalid patch, got none.")
   111  	}
   112  
   113  	file, err = ioutil.ReadFile("foo.txt")
   114  	if err != nil {
   115  		t.Fatal(err)
   116  	}
   117  
   118  	if got := string(file); got != "foo\n" {
   119  		t.Fatalf("Unexpected value of foo.txt after invalid patch: got %v want %v", got, "foo\n")
   120  	}
   121  	file, err = ioutil.ReadFile("bar.txt")
   122  	if err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	if got := string(file); got != "bar\n" {
   127  		t.Fatalf("Unexpected value of bar.txt after invalid patch: got %v want %v", got, "bar\n")
   128  	}
   129  
   130  	// Now make the work directory such that the patch should apply
   131  	if err := ioutil.WriteFile(dir+"/foo.txt", []byte("foob\n"), 0644); err != nil {
   132  		t.Fatal(err)
   133  	}
   134  	if err := Apply(c, ApplyOptions{}, []File{File(patch.Name())}); err != nil {
   135  		t.Fatalf("Unexpected error with multi-file patch %v", err)
   136  	}
   137  
   138  	file, err = ioutil.ReadFile("foo.txt")
   139  	if err != nil {
   140  		t.Fatal(err)
   141  	}
   142  
   143  	if got := string(file); got != "barr\n" {
   144  		t.Fatalf("Unexpected value of foo.txt after invalid patch: got %v want %v", got, "barr\n")
   145  	}
   146  
   147  	file, err = ioutil.ReadFile("bar.txt")
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  
   152  	if got := string(file); got != "qux\n" {
   153  		t.Fatalf("Unexpected value of bar.txt after invalid patch: got %v want %v", got, "qux\n")
   154  	}
   155  
   156  	// Test that Reverse works as expected
   157  	if err := Apply(c, ApplyOptions{Reverse: true}, []File{File(patch.Name())}); err != nil {
   158  		t.Fatalf("Unexpected error with reverse patch: %v", err)
   159  	}
   160  
   161  	file, err = ioutil.ReadFile("foo.txt")
   162  	if err != nil {
   163  		t.Fatal(err)
   164  	}
   165  
   166  	if got := string(file); got != "foob\n" {
   167  		t.Fatalf("Unexpected value of foo.txt after invalid patch: got %v want %v", got, "foob\n")
   168  	}
   169  
   170  	file, err = ioutil.ReadFile("bar.txt")
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  
   175  	if got := string(file); got != "bar\n" {
   176  		t.Fatalf("Unexpected value of bar.txt after invalid patch: got %v want %v", got, "bar\n")
   177  	}
   178  
   179  	// Ensure that a subdirectory works as expected.
   180  	if err := os.Mkdir("qux", 0755); err != nil {
   181  		t.Fatal(err)
   182  	}
   183  	if err := ioutil.WriteFile(dir+"/qux/qux.txt", []byte("qux\n"), 0644); err != nil {
   184  		t.Fatal(err)
   185  	}
   186  	if err := ioutil.WriteFile(patch.Name(), []byte(
   187  		`diff --git a/foo.txt b/foo.txt
   188  --- a/foo.txt
   189  +++ b/foo.txt
   190  @@ -1 +1 @@
   191  -foob
   192  +barr
   193  
   194  diff --git a/qux/qux.txt b/qux/qux.txt
   195  --- a/qux/qux.txt
   196  +++ b/qux/qux.txt
   197  @@ -1 +1 @@
   198  -qux
   199  +quux
   200  `), 0644); err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	if err := Apply(c, ApplyOptions{}, []File{File(patch.Name())}); err != nil {
   204  		t.Fatalf("Unexpected error with file in subdirectory: %v", err)
   205  	}
   206  
   207  	file, err = ioutil.ReadFile("foo.txt")
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  
   212  	if got := string(file); got != "barr\n" {
   213  		t.Fatalf("Unexpected value of foo.txt after invalid patch: got %v want %v", got, "barr\n")
   214  	}
   215  
   216  	file, err = ioutil.ReadFile("bar.txt")
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	if got := string(file); got != "bar\n" {
   222  		t.Fatalf("Unexpected value of bar.txt after invalid patch: got %v want %v", got, "bar\n")
   223  	}
   224  	file, err = ioutil.ReadFile("qux/qux.txt")
   225  	if err != nil {
   226  		t.Fatal(err)
   227  	}
   228  
   229  	if got := string(file); got != "quux\n" {
   230  		t.Fatalf("Unexpected value of qux/qux.txt after invalid patch: got %v want %v", got, "quux\n")
   231  	}
   232  
   233  	// Stage "foo\n" into the index.
   234  	if err := ioutil.WriteFile(dir+"/foo.txt", []byte("foo\n"), 0644); err != nil {
   235  		t.Fatal(err)
   236  	}
   237  	if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil {
   238  		t.Fatal(err)
   239  	}
   240  
   241  	// Put something else on the filesystem
   242  	if err := ioutil.WriteFile(dir+"/foo.txt", []byte("bar\n"), 0644); err != nil {
   243  		t.Fatal(err)
   244  	}
   245  	if err := ioutil.WriteFile(patch.Name(), []byte(
   246  		`diff --git a/foo.txt b/foo.txt
   247  --- a/foo.txt
   248  +++ b/foo.txt
   249  @@ -1 +1 @@
   250  -foo
   251  +bara
   252  `), 0644); err != nil {
   253  		t.Fatal(err)
   254  	}
   255  
   256  	if err := Apply(c, ApplyOptions{Cached: true}, []File{File(patch.Name())}); err != nil {
   257  		t.Fatalf("Error while applying to index: %v", err)
   258  	}
   259  	file, err = ioutil.ReadFile("foo.txt")
   260  	if err != nil {
   261  		t.Fatal(err)
   262  	}
   263  
   264  	if got := string(file); got != "bar\n" {
   265  		t.Fatalf("--cached affected filesystem with foo.txt: got %v want %v", got, "bar\n")
   266  	}
   267  
   268  	idx, err := LsFiles(c, LsFilesOptions{Cached: true}, []File{"foo.txt"})
   269  	if err != nil {
   270  		t.Fatal(err)
   271  	}
   272  	if len(idx) != 1 || idx[0].PathName != "foo.txt" {
   273  		t.Fatal("LsFiles did not return foo.txt")
   274  	}
   275  	if want := hashString("bara\n"); idx[0].Sha1 != want {
   276  		t.Errorf("Did not apply --cached patch correctly. Got %v want %v", idx[0].Sha1, want)
   277  	}
   278  }