You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

StatusTest.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /*
  2. * Copyright (C) 2012, 2015 François Rey <eclipse.org_@_francois_._rey_._name> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.pgm;
  11. import static org.eclipse.jgit.lib.Constants.MASTER;
  12. import static org.eclipse.jgit.lib.Constants.R_HEADS;
  13. import static org.junit.Assert.assertTrue;
  14. import java.io.IOException;
  15. import org.eclipse.jgit.api.Git;
  16. import org.eclipse.jgit.api.errors.GitAPIException;
  17. import org.eclipse.jgit.lib.CLIRepositoryTestCase;
  18. import org.eclipse.jgit.revwalk.RevCommit;
  19. import org.junit.Test;
  20. public class StatusTest extends CLIRepositoryTestCase {
  21. @Test
  22. public void testPathOptionHelp() throws Exception {
  23. String[] result = execute("git status -h");
  24. assertTrue("Unexpected argument: " + result[1],
  25. result[1].endsWith("[-- path ...]"));
  26. }
  27. @Test
  28. public void testStatusDefault() throws Exception {
  29. executeTest("git status", false, true);
  30. }
  31. @Test
  32. public void testStatusU() throws Exception {
  33. executeTest("git status -u", false, true);
  34. }
  35. @Test
  36. public void testStatusUno() throws Exception {
  37. executeTest("git status -uno", false, false);
  38. }
  39. @Test
  40. public void testStatusUall() throws Exception {
  41. executeTest("git status -uall", false, true);
  42. }
  43. @Test
  44. public void testStatusUntrackedFiles() throws Exception {
  45. executeTest("git status --untracked-files", false, true);
  46. }
  47. @Test
  48. public void testStatusUntrackedFilesNo() throws Exception {
  49. executeTest("git status --untracked-files=no", false, false);
  50. }
  51. @Test
  52. public void testStatusUntrackedFilesAll() throws Exception {
  53. executeTest("git status --untracked-files=all", false, true);
  54. }
  55. @Test
  56. public void testStatusPorcelain() throws Exception {
  57. executeTest("git status --porcelain", true, true);
  58. }
  59. @Test
  60. public void testStatusPorcelainU() throws Exception {
  61. executeTest("git status --porcelain -u", true, true);
  62. }
  63. @Test
  64. public void testStatusPorcelainUno() throws Exception {
  65. executeTest("git status --porcelain -uno", true, false);
  66. }
  67. @Test
  68. public void testStatusPorcelainUall() throws Exception {
  69. executeTest("git status --porcelain -uall", true, true);
  70. }
  71. @Test
  72. public void testStatusPorcelainUntrackedFiles() throws Exception {
  73. executeTest("git status --porcelain --untracked-files", true, true);
  74. }
  75. @Test
  76. public void testStatusPorcelainUntrackedFilesNo() throws Exception {
  77. executeTest("git status --porcelain --untracked-files=no", true, false);
  78. }
  79. @Test
  80. public void testStatusPorcelainUntrackedFilesAll() throws Exception {
  81. executeTest("git status --porcelain --untracked-files=all", true, true);
  82. }
  83. /**
  84. * Executes the test sequence.
  85. *
  86. * @param command
  87. * full git command and parameters to be used
  88. * @param porcelain
  89. * indicates that porcelain format is expected in the output
  90. * @param untrackedFiles
  91. * indicates that untracked files are expected in the output
  92. *
  93. * @throws Exception
  94. * if error during test execution
  95. */
  96. private void executeTest(String command, boolean porcelain,
  97. boolean untrackedFiles) throws Exception {
  98. Git git = new Git(db);
  99. // Write all files
  100. writeAllFiles();
  101. // Test untracked
  102. assertUntrackedFiles(command, porcelain, untrackedFiles);
  103. // Add to index
  104. addFilesToIndex(git);
  105. // Test staged count
  106. assertStagedFiles(command, porcelain, untrackedFiles);
  107. // Commit
  108. makeInitialCommit(git);
  109. assertAfterInitialCommit(command, porcelain, untrackedFiles);
  110. // Make some changes and stage them
  111. makeSomeChangesAndStageThem(git);
  112. // Test staged/not-staged status
  113. assertStagedStatus(command, porcelain, untrackedFiles);
  114. // Create unmerged file
  115. createUnmergedFile(git);
  116. // Commit pending changes
  117. commitPendingChanges(git);
  118. assertUntracked(command, porcelain, untrackedFiles, "master");
  119. // Checkout new branch
  120. checkoutTestBranch(git);
  121. // Test branch status
  122. assertUntracked(command, porcelain, untrackedFiles, "test");
  123. // Commit change and checkout master again
  124. RevCommit testBranch = commitChangesInTestBranch(git);
  125. assertUntracked(command, porcelain, untrackedFiles, "test");
  126. checkoutMasterBranch(git);
  127. // Change the same file and commit
  128. changeUnmergedFileAndCommit(git);
  129. assertUntracked(command, porcelain, untrackedFiles, "master");
  130. // Merge test branch into master
  131. mergeTestBranchInMaster(git, testBranch);
  132. // Test unmerged status
  133. assertUntrackedAndUnmerged(command, porcelain, untrackedFiles, "master");
  134. // Test detached head
  135. detachHead(git);
  136. assertUntrackedAndUnmerged(command, porcelain, untrackedFiles, null);
  137. }
  138. private void writeAllFiles() throws IOException {
  139. writeTrashFile("tracked", "tracked");
  140. writeTrashFile("stagedNew", "stagedNew");
  141. writeTrashFile("stagedModified", "stagedModified");
  142. writeTrashFile("stagedDeleted", "stagedDeleted");
  143. writeTrashFile("trackedModified", "trackedModified");
  144. writeTrashFile("trackedDeleted", "trackedDeleted");
  145. writeTrashFile("untracked", "untracked");
  146. }
  147. private void addFilesToIndex(Git git) throws GitAPIException {
  148. git.add().addFilepattern("tracked").call();
  149. git.add().addFilepattern("stagedModified").call();
  150. git.add().addFilepattern("stagedDeleted").call();
  151. git.add().addFilepattern("trackedModified").call();
  152. git.add().addFilepattern("trackedDeleted").call();
  153. }
  154. private void makeInitialCommit(Git git) throws GitAPIException {
  155. git.commit().setMessage("initial commit").call();
  156. }
  157. private void makeSomeChangesAndStageThem(Git git) throws IOException,
  158. GitAPIException {
  159. writeTrashFile("stagedModified", "stagedModified modified");
  160. deleteTrashFile("stagedDeleted");
  161. writeTrashFile("trackedModified", "trackedModified modified");
  162. deleteTrashFile("trackedDeleted");
  163. git.add().addFilepattern("stagedModified").call();
  164. git.rm().addFilepattern("stagedDeleted").call();
  165. git.add().addFilepattern("stagedNew").call();
  166. }
  167. private void createUnmergedFile(Git git) throws IOException,
  168. GitAPIException {
  169. writeTrashFile("unmerged", "unmerged");
  170. git.add().addFilepattern("unmerged").call();
  171. }
  172. private void commitPendingChanges(Git git) throws GitAPIException {
  173. git.add().addFilepattern("trackedModified").call();
  174. git.rm().addFilepattern("trackedDeleted").call();
  175. git.commit().setMessage("commit before branching").call();
  176. }
  177. private void checkoutTestBranch(Git git) throws GitAPIException {
  178. git.checkout().setCreateBranch(true).setName("test").call();
  179. }
  180. private RevCommit commitChangesInTestBranch(Git git) throws IOException,
  181. GitAPIException {
  182. writeTrashFile("unmerged", "changed in test branch");
  183. git.add().addFilepattern("unmerged").call();
  184. return git.commit()
  185. .setMessage("changed unmerged in test branch").call();
  186. }
  187. private void checkoutMasterBranch(Git git) throws GitAPIException {
  188. git.checkout().setName("master").call();
  189. }
  190. private void changeUnmergedFileAndCommit(Git git) throws IOException,
  191. GitAPIException {
  192. writeTrashFile("unmerged", "changed in master branch");
  193. git.add().addFilepattern("unmerged").call();
  194. git.commit().setMessage("changed unmerged in master branch").call();
  195. }
  196. private void mergeTestBranchInMaster(Git git, RevCommit aCommit)
  197. throws GitAPIException {
  198. git.merge().include(aCommit.getId()).call();
  199. }
  200. private void detachHead(Git git) throws IOException, GitAPIException {
  201. String commitId = db.exactRef(R_HEADS + MASTER).getObjectId().name();
  202. git.checkout().setName(commitId).call();
  203. }
  204. private void assertUntrackedFiles(String command, boolean porcelain,
  205. boolean untrackedFiles) throws Exception {
  206. String[] output = new String[0];
  207. if (porcelain) {
  208. if (untrackedFiles) {
  209. output = new String[] { //
  210. "?? stagedDeleted", //
  211. "?? stagedModified", //
  212. "?? stagedNew", //
  213. "?? tracked", //
  214. "?? trackedDeleted", //
  215. "?? trackedModified", //
  216. "?? untracked", //
  217. "" //
  218. };
  219. } else {
  220. output = new String[] { //
  221. "" //
  222. };
  223. }
  224. } else {
  225. if (untrackedFiles) {
  226. output = new String[] { //
  227. "On branch master", //
  228. "Untracked files:", //
  229. "",//
  230. "\tstagedDeleted", //
  231. "\tstagedModified", //
  232. "\tstagedNew", //
  233. "\ttracked", //
  234. "\ttrackedDeleted", //
  235. "\ttrackedModified", //
  236. "\tuntracked", //
  237. "" //
  238. };
  239. } else {
  240. output = new String[] { //
  241. "On branch master", //
  242. "" //
  243. };
  244. }
  245. }
  246. assertArrayOfLinesEquals(output, execute(command));
  247. }
  248. private void assertStagedFiles(String command, boolean porcelain,
  249. boolean untrackedFiles) throws Exception {
  250. String[] output = new String[0];
  251. if (porcelain) {
  252. if (untrackedFiles) {
  253. output = new String[] { //
  254. "A stagedDeleted", //
  255. "A stagedModified", //
  256. "A tracked", //
  257. "A trackedDeleted", //
  258. "A trackedModified", //
  259. "?? stagedNew", //
  260. "?? untracked", //
  261. "" //
  262. };
  263. } else {
  264. output = new String[] { //
  265. "A stagedDeleted", //
  266. "A stagedModified", //
  267. "A tracked", //
  268. "A trackedDeleted", //
  269. "A trackedModified", //
  270. "" //
  271. };
  272. }
  273. } else {
  274. if (untrackedFiles) {
  275. output = new String[] { //
  276. "On branch master", //
  277. "Changes to be committed:", //
  278. "", //
  279. "\tnew file: stagedDeleted", //
  280. "\tnew file: stagedModified", //
  281. "\tnew file: tracked", //
  282. "\tnew file: trackedDeleted", //
  283. "\tnew file: trackedModified", //
  284. "", //
  285. "Untracked files:", //
  286. "", //
  287. "\tstagedNew", //
  288. "\tuntracked", //
  289. "" //
  290. };
  291. } else {
  292. output = new String[] { //
  293. "On branch master", //
  294. "Changes to be committed:", //
  295. "", //
  296. "\tnew file: stagedDeleted", //
  297. "\tnew file: stagedModified", //
  298. "\tnew file: tracked", //
  299. "\tnew file: trackedDeleted", //
  300. "\tnew file: trackedModified", //
  301. "" //
  302. };
  303. }
  304. }
  305. assertArrayOfLinesEquals(output, execute(command));
  306. }
  307. private void assertAfterInitialCommit(String command, boolean porcelain,
  308. boolean untrackedFiles) throws Exception {
  309. String[] output = new String[0];
  310. if (porcelain) {
  311. if (untrackedFiles) {
  312. output = new String[] { //
  313. "?? stagedNew", //
  314. "?? untracked", //
  315. "" //
  316. };
  317. } else {
  318. output = new String[] { //
  319. "" //
  320. };
  321. }
  322. } else {
  323. if (untrackedFiles) {
  324. output = new String[] { //
  325. "On branch master", //
  326. "Untracked files:", //
  327. "", //
  328. "\tstagedNew", //
  329. "\tuntracked", //
  330. "" //
  331. };
  332. } else {
  333. output = new String[] { //
  334. "On branch master", //
  335. "" //
  336. };
  337. }
  338. }
  339. assertArrayOfLinesEquals(output, execute(command));
  340. }
  341. private void assertStagedStatus(String command, boolean porcelain,
  342. boolean untrackedFiles) throws Exception {
  343. String[] output = new String[0];
  344. if (porcelain) {
  345. if (untrackedFiles) {
  346. output = new String[] { //
  347. "D stagedDeleted", //
  348. "M stagedModified", //
  349. "A stagedNew", //
  350. " D trackedDeleted", //
  351. " M trackedModified", //
  352. "?? untracked", //
  353. "" //
  354. };
  355. } else {
  356. output = new String[] { //
  357. "D stagedDeleted", //
  358. "M stagedModified", //
  359. "A stagedNew", //
  360. " D trackedDeleted", //
  361. " M trackedModified", //
  362. "" //
  363. };
  364. }
  365. } else {
  366. if (untrackedFiles) {
  367. output = new String[] { //
  368. "On branch master", //
  369. "Changes to be committed:", //
  370. "", //
  371. "\tdeleted: stagedDeleted", //
  372. "\tmodified: stagedModified", //
  373. "\tnew file: stagedNew", //
  374. "", //
  375. "Changes not staged for commit:", //
  376. "", //
  377. "\tdeleted: trackedDeleted", //
  378. "\tmodified: trackedModified", //
  379. "", //
  380. "Untracked files:", //
  381. "", //
  382. "\tuntracked", //
  383. "" //
  384. };
  385. } else {
  386. output = new String[] { //
  387. "On branch master", //
  388. "Changes to be committed:", //
  389. "", //
  390. "\tdeleted: stagedDeleted", //
  391. "\tmodified: stagedModified", //
  392. "\tnew file: stagedNew", //
  393. "", //
  394. "Changes not staged for commit:", //
  395. "", //
  396. "\tdeleted: trackedDeleted", //
  397. "\tmodified: trackedModified", //
  398. "", //
  399. };
  400. }
  401. }
  402. assertArrayOfLinesEquals(output, execute(command));
  403. }
  404. private void assertUntracked(String command,
  405. boolean porcelain,
  406. boolean untrackedFiles, String branch) throws Exception {
  407. String[] output = new String[0];
  408. String branchHeader = "On branch " + branch;
  409. if (porcelain) {
  410. if (untrackedFiles) {
  411. output = new String[] { //
  412. "?? untracked", //
  413. "" //
  414. };
  415. } else {
  416. output = new String[] { //
  417. "" //
  418. };
  419. }
  420. } else {
  421. if (untrackedFiles) {
  422. output = new String[] { //
  423. branchHeader, //
  424. "Untracked files:", //
  425. "", //
  426. "\tuntracked", //
  427. "" //
  428. };
  429. } else {
  430. output = new String[] { //
  431. branchHeader, //
  432. "" //
  433. };
  434. }
  435. }
  436. assertArrayOfLinesEquals(output, execute(command));
  437. }
  438. private void assertUntrackedAndUnmerged(String command, boolean porcelain,
  439. boolean untrackedFiles, String branch) throws Exception {
  440. String[] output = new String[0];
  441. String branchHeader = (branch == null) //
  442. ? "Not currently on any branch." //
  443. : "On branch " + branch;
  444. if (porcelain) {
  445. if (untrackedFiles) {
  446. output = new String[] { //
  447. "UU unmerged", //
  448. "?? untracked", //
  449. "" //
  450. };
  451. } else {
  452. output = new String[] { //
  453. "UU unmerged", //
  454. "" //
  455. };
  456. }
  457. } else {
  458. if (untrackedFiles) {
  459. output = new String[] { //
  460. branchHeader, //
  461. "Unmerged paths:", //
  462. "", //
  463. "\tboth modified: unmerged", //
  464. "", //
  465. "Untracked files:", //
  466. "", //
  467. "\tuntracked", //
  468. "" //
  469. };
  470. } else {
  471. output = new String[] { //
  472. branchHeader, //
  473. "Unmerged paths:", //
  474. "", //
  475. "\tboth modified: unmerged", //
  476. "" //
  477. };
  478. }
  479. }
  480. assertArrayOfLinesEquals(output, execute(command));
  481. }
  482. }