github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/status_test.go (about) 1 package git 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "testing" 8 ) 9 10 type expectedStatus struct { 11 Long, Short, ShortBranch, PorcelainV2 string 12 } 13 14 func compareStatus(c *Client, opts StatusOptions, expected expectedStatus) error { 15 opts.Short = false 16 opts.Branch = false 17 opts.Porcelain = 0 18 opts.Long = true 19 s, err := Status(c, opts, nil) 20 if err != nil { 21 return fmt.Errorf("Long status: %v", err) 22 } 23 if expected.Long != s { 24 return fmt.Errorf("Long status: got `%v` want `%v`", s, expected.Long) 25 } 26 opts.Long = false 27 opts.Short = true 28 s, err = Status(c, opts, nil) 29 if err != nil { 30 return fmt.Errorf("Short status: %v", err) 31 } 32 if expected.Short != s { 33 return fmt.Errorf("Short status: got `%v` want `%v`", s, expected.Short) 34 } 35 opts.Branch = true 36 s, err = Status(c, opts, nil) 37 if err != nil { 38 return fmt.Errorf("Short branch status: `%v`", err) 39 } 40 if expected.ShortBranch != s { 41 return fmt.Errorf("Short branch status: got `%v` want `%v`", s, expected.ShortBranch) 42 } 43 return nil 44 /* 45 // Porcelain=2 isn't supported yet, so this is commented out 46 opts.Porcelain = 2 47 opts.Short = false 48 opts.Long = false 49 s, err = Status(c, opts, nil) 50 if err != nil { 51 return fmt.Errorf("Porcelain v2 status: %v", err) 52 } 53 if expected.ShortBranch != s { 54 return fmt.Errorf("Porcelain v2 status: got %v want %v", s, expected.PorcelainV2) 55 } 56 */ 57 } 58 59 // TestSimpleCommits tests that an initial commit works, 60 // and that a second commit using it as a parent works. 61 // It also tests that the second commit can be done while 62 // in a detached head mode. 63 func TestStatus(t *testing.T) { 64 if os.Getenv("SkipKnownFailures") == "true" { 65 fmt.Printf("Skipping known failure.\n") 66 return 67 } 68 69 dir, err := ioutil.TempDir("", "gitstatus") 70 if err != nil { 71 t.Fatal(err) 72 } 73 defer os.RemoveAll(dir) 74 75 // Init a repo to test an initial commit in. 76 c, err := Init(nil, InitOptions{Quiet: true}, dir) 77 if err != nil { 78 t.Fatal(err) 79 } 80 if err := os.Chdir(dir); err != nil { 81 t.Fatal(err) 82 } 83 84 if err := compareStatus(c, StatusOptions{}, expectedStatus{ 85 Long: `On branch master 86 87 No commits yet 88 89 nothing to commit (create/copy files and use "git add" to track) 90 `, 91 Short: "", 92 ShortBranch: "## No commits yet on master\n", 93 PorcelainV2: `# branch.oid (initial) 94 # branch.head master 95 `, 96 }); err != nil { 97 t.Error(err) 98 } 99 100 if ioutil.WriteFile("foo.txt", []byte("foo\n"), 0644); err != nil { 101 t.Fatal(err) 102 } 103 104 if err := compareStatus(c, StatusOptions{ 105 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 106 Long: `On branch master 107 108 No commits yet 109 110 Untracked files: 111 (use "git add <file>..." to include in what will be committed) 112 113 foo.txt 114 115 nothing added to commit but untracked files present (use "git add" to track) 116 `, 117 Short: "?? foo.txt\n", 118 ShortBranch: `## No commits yet on master 119 ?? foo.txt 120 `, 121 PorcelainV2: `# branch.oid (initial) 122 # branch.head master 123 ? foo.txt 124 `, 125 }); err != nil { 126 t.Error(err) 127 } 128 129 if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil { 130 t.Fatal(err) 131 } 132 133 if err := compareStatus(c, StatusOptions{ 134 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 135 Long: `On branch master 136 137 No commits yet 138 139 Changes to be committed: 140 (use "git rm --cached <file>..." to unstage) 141 142 new file: foo.txt 143 144 `, 145 Short: "A foo.txt\n", 146 ShortBranch: `## No commits yet on master 147 A foo.txt 148 `, 149 PorcelainV2: `# branch.oid (initial) 150 # branch.head master 151 1 A. N... 000000 100644 100644 00000000000000000000000000000000000000 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 foo.txt 152 `, 153 }); err != nil { 154 t.Error(err) 155 } 156 157 if ioutil.WriteFile("foo.txt", []byte("bar\n"), 0644); err != nil { 158 t.Fatal(err) 159 } 160 161 if err := compareStatus(c, StatusOptions{ 162 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 163 Long: `On branch master 164 165 No commits yet 166 167 Changes to be committed: 168 (use "git rm --cached <file>..." to unstage) 169 170 new file: foo.txt 171 172 Changes not staged for commit: 173 (use "git add <file>..." to update what will be committed) 174 (use "git checkout -- <file>..." to discard changes in working directory) 175 176 modified: foo.txt 177 178 `, 179 Short: "AM foo.txt\n", 180 ShortBranch: `## No commits yet on master 181 AM foo.txt 182 `, 183 PorcelainV2: `# branch.oid (initial) 184 # branch.head master 185 1 AM N... 000000 100644 100644 00000000000000000000000000000000000000 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 foo.txt 186 `, 187 }); err != nil { 188 t.Error(err) 189 } 190 191 initial, err := Commit(c, CommitOptions{}, "Status test", nil) 192 if err != nil { 193 t.Fatal(err) 194 } 195 if err := compareStatus(c, StatusOptions{ 196 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 197 Long: `On branch master 198 Changes not staged for commit: 199 (use "git add <file>..." to update what will be committed) 200 (use "git checkout -- <file>..." to discard changes in working directory) 201 202 modified: foo.txt 203 204 no changes added to commit (use "git add" and/or "git commit -a") 205 `, 206 Short: " M foo.txt\n", 207 ShortBranch: `## master 208 M foo.txt 209 `, 210 PorcelainV2: `# branch.oid (initial) 211 # branch.head master 212 1 .M N... 000000 100644 100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 foo.txt 213 `, 214 }); err != nil { 215 t.Error(err) 216 } 217 218 if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil { 219 t.Fatal(err) 220 } 221 c2, err := Commit(c, CommitOptions{}, "Status test2", nil) 222 if err != nil { 223 t.Fatal(err) 224 } 225 if err := compareStatus(c, StatusOptions{ 226 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 227 Long: `On branch master 228 nothing to commit, working tree clean 229 `, 230 Short: "", 231 ShortBranch: `## master 232 `, 233 // FIXME: Need to make the commit ID deterministic 234 // in order for this to work. 235 PorcelainV2: `# branch.oid deadbeefdeadbeefdeadbeefetc 236 # branch.head master 237 `, 238 }); err != nil { 239 t.Error(err) 240 } 241 242 if err := CheckoutCommit(c, CheckoutOptions{}, initial); err != nil { 243 t.Fatal(err) 244 } 245 246 var cid string 247 if comm, err := initial.CommitID(c); err != nil && err != DetachedHead { 248 t.Fatal(err) 249 } else { 250 cid = comm.String() 251 } 252 253 if err := compareStatus(c, StatusOptions{ 254 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 255 Long: `HEAD detached at ` + cid + ` 256 nothing to commit, working tree clean 257 `, 258 Short: "", 259 ShortBranch: `## HEAD (no branch) 260 `, 261 PorcelainV2: `# branch.oid ` + cid + ` 262 # branch.head (detached) 263 `, 264 }); err != nil { 265 t.Error(err) 266 } 267 268 // Make a third commit so that we can use readtree to produce a conflict. 269 if ioutil.WriteFile("foo.txt", []byte("baz\n"), 0644); err != nil { 270 t.Fatal(err) 271 } 272 if _, err := Add(c, AddOptions{}, []File{"foo.txt"}); err != nil { 273 t.Fatal(err) 274 } 275 c3, err := Commit(c, CommitOptions{}, "Status test3", nil) 276 if err != nil { 277 t.Fatal(err) 278 } 279 if _, err := ReadTreeThreeWay(c, ReadTreeOptions{}, initial, c2, c3); err != nil { 280 t.Fatal(err) 281 } 282 cid = c3.String() 283 if err := compareStatus(c, StatusOptions{ 284 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 285 Long: `HEAD detached at ` + cid + ` 286 Unmerged paths: 287 (use "git reset HEAD <file>..." to unstage) 288 (use "git add <file>..." to mark resolution) 289 290 both modified: foo.txt 291 292 no changes added to commit (use "git add" and/or "git commit -a") 293 `, 294 Short: "UU foo.txt\n", 295 ShortBranch: `## HEAD (no branch) 296 UU foo.txt 297 `, 298 PorcelainV2: ``, // FIXME: Check what this should be. 299 }); err != nil { 300 t.Error(err) 301 } 302 303 // Finally, put some things in subdirectories and have a mixed status 304 // to make sure things work when we're in a subdirectory and to try 305 // the different untracked modes. 306 if ioutil.WriteFile("bar.txt", []byte("bar\n"), 0644); err != nil { 307 t.Fatal(err) 308 } 309 if _, err := Add(c, AddOptions{}, []File{"bar.txt"}); err != nil { 310 t.Fatal(err) 311 } 312 if err := ioutil.WriteFile("bar.txt", []byte("baz\n"), 0644); err != nil { 313 t.Fatal(err) 314 } 315 if err := os.Mkdir("baz", 0755); err != nil { 316 t.Fatal(err) 317 } 318 if err := os.Mkdir("baz2", 0755); err != nil { 319 t.Fatal(err) 320 } 321 if err := ioutil.WriteFile("baz/bar.txt", []byte("bar\n"), 0644); err != nil { 322 t.Fatal(err) 323 } 324 if err := ioutil.WriteFile("baz/foo.txt", []byte("bar\n"), 0644); err != nil { 325 t.Fatal(err) 326 } 327 if err := ioutil.WriteFile("baz2/bar.txt", []byte("bar\n"), 0644); err != nil { 328 t.Fatal(err) 329 } 330 if err := ioutil.WriteFile("baz2/foo.txt", []byte("bar\n"), 0644); err != nil { 331 t.Fatal(err) 332 } 333 if _, err := Add(c, AddOptions{}, []File{"baz/foo.txt"}); err != nil { 334 t.Fatal(err) 335 } 336 if err := compareStatus(c, StatusOptions{ 337 UntrackedMode: StatusUntrackedNo}, expectedStatus{ 338 Long: `HEAD detached at ` + cid + ` 339 Changes to be committed: 340 (use "git reset HEAD <file>..." to unstage) 341 342 new file: bar.txt 343 new file: baz/foo.txt 344 345 Unmerged paths: 346 (use "git reset HEAD <file>..." to unstage) 347 (use "git add <file>..." to mark resolution) 348 349 both modified: foo.txt 350 351 Changes not staged for commit: 352 (use "git add <file>..." to update what will be committed) 353 (use "git checkout -- <file>..." to discard changes in working directory) 354 355 modified: bar.txt 356 357 Untracked files not listed (use -u option to show untracked files) 358 `, 359 Short: `AM bar.txt 360 A baz/foo.txt 361 UU foo.txt 362 `, 363 ShortBranch: `## HEAD (no branch) 364 AM bar.txt 365 A baz/foo.txt 366 UU foo.txt 367 `, 368 PorcelainV2: ``, // FIXME: Check what this should be. 369 }); err != nil { 370 t.Error(err) 371 } 372 if os.Chdir("baz2"); err != nil { 373 t.Fatal(err) 374 } 375 376 // Try it in a subdirectory with -unormal 377 if err := compareStatus(c, StatusOptions{ 378 UntrackedMode: StatusUntrackedNormal}, expectedStatus{ 379 Long: `HEAD detached at ` + cid + ` 380 Changes to be committed: 381 (use "git reset HEAD <file>..." to unstage) 382 383 new file: ../bar.txt 384 new file: ../baz/foo.txt 385 386 Unmerged paths: 387 (use "git reset HEAD <file>..." to unstage) 388 (use "git add <file>..." to mark resolution) 389 390 both modified: ../foo.txt 391 392 Changes not staged for commit: 393 (use "git add <file>..." to update what will be committed) 394 (use "git checkout -- <file>..." to discard changes in working directory) 395 396 modified: ../bar.txt 397 398 Untracked files: 399 (use "git add <file>..." to include in what will be committed) 400 401 ../baz/bar.txt 402 ./ 403 404 `, 405 Short: `AM ../bar.txt 406 A ../baz/foo.txt 407 UU ../foo.txt 408 ?? ../baz/bar.txt 409 ?? ./ 410 `, 411 ShortBranch: `## HEAD (no branch) 412 AM ../bar.txt 413 A ../baz/foo.txt 414 UU ../foo.txt 415 ?? ../baz/bar.txt 416 ?? ./ 417 `, 418 PorcelainV2: ``, // FIXME: Check what this should be. 419 }); err != nil { 420 t.Error(err) 421 } 422 423 // Try the same thing with -uall 424 if err := compareStatus(c, StatusOptions{ 425 UntrackedMode: StatusUntrackedAll}, expectedStatus{ 426 Long: `HEAD detached at ` + cid + ` 427 Changes to be committed: 428 (use "git reset HEAD <file>..." to unstage) 429 430 new file: ../bar.txt 431 new file: ../baz/foo.txt 432 433 Unmerged paths: 434 (use "git reset HEAD <file>..." to unstage) 435 (use "git add <file>..." to mark resolution) 436 437 both modified: ../foo.txt 438 439 Changes not staged for commit: 440 (use "git add <file>..." to update what will be committed) 441 (use "git checkout -- <file>..." to discard changes in working directory) 442 443 modified: ../bar.txt 444 445 Untracked files: 446 (use "git add <file>..." to include in what will be committed) 447 448 ../baz/bar.txt 449 bar.txt 450 foo.txt 451 452 `, 453 Short: `AM ../bar.txt 454 A ../baz/foo.txt 455 UU ../foo.txt 456 ?? ../baz/bar.txt 457 ?? bar.txt 458 ?? foo.txt 459 `, 460 ShortBranch: `## HEAD (no branch) 461 AM ../bar.txt 462 A ../baz/foo.txt 463 UU ../foo.txt 464 ?? ../baz/bar.txt 465 ?? bar.txt 466 ?? foo.txt 467 `, 468 PorcelainV2: ``, // FIXME: Check what this should be. 469 }); err != nil { 470 t.Error(err) 471 } 472 }