123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464 |
- /*
- * Copyright (C) 2012, GitHub Inc.
- * and other copyright owners as documented in the project's IP log.
- *
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Distribution License v1.0 which
- * accompanies this distribution, is reproduced below, and is
- * available at http://www.eclipse.org/org/documents/edl-v10.php
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials provided
- * with the distribution.
- *
- * - Neither the name of the Eclipse Foundation, Inc. nor the
- * names of its contributors may be used to endorse or promote
- * products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- package org.eclipse.jgit.api;
-
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertFalse;
- import static org.junit.Assert.assertNotNull;
- import static org.junit.Assert.assertNull;
- import static org.junit.Assert.assertTrue;
-
- import java.io.File;
- import java.io.IOException;
- import java.util.List;
-
- import org.eclipse.jgit.api.errors.UnmergedPathsException;
- import org.eclipse.jgit.diff.DiffEntry;
- import org.eclipse.jgit.junit.RepositoryTestCase;
- import org.eclipse.jgit.lib.Constants;
- import org.eclipse.jgit.lib.ObjectId;
- import org.eclipse.jgit.lib.PersonIdent;
- import org.eclipse.jgit.lib.Ref;
- import org.eclipse.jgit.lib.ReflogEntry;
- import org.eclipse.jgit.lib.ReflogReader;
- import org.eclipse.jgit.revwalk.RevCommit;
- import org.eclipse.jgit.revwalk.RevWalk;
- import org.eclipse.jgit.treewalk.TreeWalk;
- import org.eclipse.jgit.treewalk.filter.TreeFilter;
- import org.eclipse.jgit.util.FileUtils;
- import org.junit.Before;
- import org.junit.Test;
-
- /**
- * Unit tests of {@link StashCreateCommand}
- */
- public class StashCreateCommandTest extends RepositoryTestCase {
-
- private RevCommit head;
-
- private Git git;
-
- private File committedFile;
-
- @Before
- public void setUp() throws Exception {
- super.setUp();
- git = Git.wrap(db);
- committedFile = writeTrashFile("file.txt", "content");
- git.add().addFilepattern("file.txt").call();
- head = git.commit().setMessage("add file").call();
- assertNotNull(head);
- writeTrashFile("untracked.txt", "content");
- }
-
- /**
- * Core validation to be performed on all stashed commits
- *
- * @param commit
- * @throws IOException
- */
- private void validateStashedCommit(final RevCommit commit)
- throws IOException {
- assertNotNull(commit);
- Ref stashRef = db.getRef(Constants.R_STASH);
- assertNotNull(stashRef);
- assertEquals(commit, stashRef.getObjectId());
- assertNotNull(commit.getAuthorIdent());
- assertEquals(commit.getAuthorIdent(), commit.getCommitterIdent());
- assertEquals(2, commit.getParentCount());
-
- // Load parents
- RevWalk walk = new RevWalk(db);
- try {
- for (RevCommit parent : commit.getParents())
- walk.parseBody(parent);
- } finally {
- walk.release();
- }
-
- assertEquals(1, commit.getParent(1).getParentCount());
- assertEquals(head, commit.getParent(1).getParent(0));
- assertFalse("Head tree matches stashed commit tree", commit.getTree()
- .equals(head.getTree()));
- assertEquals(head, commit.getParent(0));
- assertFalse(commit.getFullMessage().equals(
- commit.getParent(1).getFullMessage()));
- }
-
- private TreeWalk createTreeWalk() {
- TreeWalk walk = new TreeWalk(db);
- walk.setRecursive(true);
- walk.setFilter(TreeFilter.ANY_DIFF);
- return walk;
- }
-
- private List<DiffEntry> diffWorkingAgainstHead(final RevCommit commit)
- throws IOException {
- TreeWalk walk = createTreeWalk();
- try {
- walk.addTree(commit.getParent(0).getTree());
- walk.addTree(commit.getTree());
- return DiffEntry.scan(walk);
- } finally {
- walk.release();
- }
- }
-
- private List<DiffEntry> diffIndexAgainstHead(final RevCommit commit)
- throws IOException {
- TreeWalk walk = createTreeWalk();
- try {
- walk.addTree(commit.getParent(0).getTree());
- walk.addTree(commit.getParent(1).getTree());
- return DiffEntry.scan(walk);
- } finally {
- walk.release();
- }
- }
-
- private List<DiffEntry> diffIndexAgainstWorking(final RevCommit commit)
- throws IOException {
- TreeWalk walk = createTreeWalk();
- try {
- walk.addTree(commit.getParent(1).getTree());
- walk.addTree(commit.getTree());
- return DiffEntry.scan(walk);
- } finally {
- walk.release();
- }
- }
-
- @Test
- public void noLocalChanges() throws Exception {
- assertNull(git.stashCreate().call());
- }
-
- @Test
- public void workingDirectoryDelete() throws Exception {
- deleteTrashFile("file.txt");
- RevCommit stashed = git.stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertEquals(head.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, diffs.size());
- assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
- assertEquals("file.txt", diffs.get(0).getOldPath());
- }
-
- @Test
- public void indexAdd() throws Exception {
- File addedFile = writeTrashFile("file2.txt", "content2");
- git.add().addFilepattern("file2.txt").call();
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertFalse(addedFile.exists());
- validateStashedCommit(stashed);
-
- assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, diffs.size());
- assertEquals(DiffEntry.ChangeType.ADD, diffs.get(0).getChangeType());
- assertEquals("file2.txt", diffs.get(0).getNewPath());
- }
-
- @Test
- public void newFileInIndexThenModifiedInWorkTree() throws Exception {
- writeTrashFile("file", "content");
- git.add().addFilepattern("file").call();
- writeTrashFile("file", "content2");
- RevCommit stashedWorkTree = Git.wrap(db).stashCreate().call();
- validateStashedCommit(stashedWorkTree);
- RevWalk walk = new RevWalk(db);
- RevCommit stashedIndex = stashedWorkTree.getParent(1);
- walk.parseBody(stashedIndex);
- walk.parseBody(stashedIndex.getTree());
- walk.parseBody(stashedIndex.getParent(0));
- List<DiffEntry> workTreeStashAgainstWorkTree = diffWorkingAgainstHead(stashedWorkTree);
- assertEquals(1, workTreeStashAgainstWorkTree.size());
- List<DiffEntry> workIndexAgainstWorkTree = diffIndexAgainstHead(stashedWorkTree);
- assertEquals(1, workIndexAgainstWorkTree.size());
- List<DiffEntry> indexStashAgainstWorkTree = diffIndexAgainstWorking(stashedWorkTree);
- assertEquals(1, indexStashAgainstWorkTree.size());
- }
-
- @Test
- public void indexDelete() throws Exception {
- git.rm().addFilepattern("file.txt").call();
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, diffs.size());
- assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
- assertEquals("file.txt", diffs.get(0).getOldPath());
- }
-
- @Test
- public void workingDirectoryModify() throws Exception {
- writeTrashFile("file.txt", "content2");
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertEquals(head.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, diffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
- assertEquals("file.txt", diffs.get(0).getNewPath());
- }
-
- @Test
- public void workingDirectoryModifyInSubfolder() throws Exception {
- String path = "d1/d2/f.txt";
- File subfolderFile = writeTrashFile(path, "content");
- git.add().addFilepattern(path).call();
- head = git.commit().setMessage("add file").call();
-
- writeTrashFile(path, "content2");
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(subfolderFile));
- validateStashedCommit(stashed);
-
- assertEquals(head.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, diffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, diffs.get(0).getChangeType());
- assertEquals(path, diffs.get(0).getNewPath());
- }
-
- @Test
- public void workingDirectoryModifyIndexChanged() throws Exception {
- writeTrashFile("file.txt", "content2");
- git.add().addFilepattern("file.txt").call();
- writeTrashFile("file.txt", "content3");
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertFalse(stashed.getTree().equals(stashed.getParent(1).getTree()));
-
- List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, workingDiffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, workingDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", workingDiffs.get(0).getNewPath());
-
- List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
- assertEquals(1, indexDiffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", indexDiffs.get(0).getNewPath());
-
- assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
- .getOldId());
- assertFalse(workingDiffs.get(0).getNewId()
- .equals(indexDiffs.get(0).getNewId()));
- }
-
- @Test
- public void workingDirectoryCleanIndexModify() throws Exception {
- writeTrashFile("file.txt", "content2");
- git.add().addFilepattern("file.txt").call();
- writeTrashFile("file.txt", "content");
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertEquals(stashed.getParent(1).getTree(), stashed.getTree());
-
- List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, workingDiffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, workingDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", workingDiffs.get(0).getNewPath());
-
- List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
- assertEquals(1, indexDiffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", indexDiffs.get(0).getNewPath());
-
- assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
- .getOldId());
- assertTrue(workingDiffs.get(0).getNewId()
- .equals(indexDiffs.get(0).getNewId()));
- }
-
- @Test
- public void workingDirectoryDeleteIndexAdd() throws Exception {
- String path = "file2.txt";
- File added = writeTrashFile(path, "content2");
- assertTrue(added.exists());
- git.add().addFilepattern(path).call();
- FileUtils.delete(added);
- assertFalse(added.exists());
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertFalse(added.exists());
-
- validateStashedCommit(stashed);
-
- assertEquals(stashed.getParent(1).getTree(), stashed.getTree());
-
- List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, workingDiffs.size());
- assertEquals(DiffEntry.ChangeType.ADD, workingDiffs.get(0)
- .getChangeType());
- assertEquals(path, workingDiffs.get(0).getNewPath());
-
- List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
- assertEquals(1, indexDiffs.size());
- assertEquals(DiffEntry.ChangeType.ADD, indexDiffs.get(0)
- .getChangeType());
- assertEquals(path, indexDiffs.get(0).getNewPath());
-
- assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
- .getOldId());
- assertTrue(workingDiffs.get(0).getNewId()
- .equals(indexDiffs.get(0).getNewId()));
- }
-
- @Test
- public void workingDirectoryDeleteIndexEdit() throws Exception {
- File edited = writeTrashFile("file.txt", "content2");
- git.add().addFilepattern("file.txt").call();
- FileUtils.delete(edited);
- assertFalse(edited.exists());
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- assertFalse(stashed.getTree().equals(stashed.getParent(1).getTree()));
-
- List<DiffEntry> workingDiffs = diffWorkingAgainstHead(stashed);
- assertEquals(1, workingDiffs.size());
- assertEquals(DiffEntry.ChangeType.DELETE, workingDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", workingDiffs.get(0).getOldPath());
-
- List<DiffEntry> indexDiffs = diffIndexAgainstHead(stashed);
- assertEquals(1, indexDiffs.size());
- assertEquals(DiffEntry.ChangeType.MODIFY, indexDiffs.get(0)
- .getChangeType());
- assertEquals("file.txt", indexDiffs.get(0).getNewPath());
-
- assertEquals(workingDiffs.get(0).getOldId(), indexDiffs.get(0)
- .getOldId());
- assertFalse(workingDiffs.get(0).getNewId()
- .equals(indexDiffs.get(0).getNewId()));
- }
-
- @Test
- public void multipleEdits() throws Exception {
- git.rm().addFilepattern("file.txt").call();
- File addedFile = writeTrashFile("file2.txt", "content2");
- git.add().addFilepattern("file2.txt").call();
-
- RevCommit stashed = Git.wrap(db).stashCreate().call();
- assertNotNull(stashed);
- assertFalse(addedFile.exists());
- validateStashedCommit(stashed);
-
- assertEquals(stashed.getTree(), stashed.getParent(1).getTree());
-
- List<DiffEntry> diffs = diffWorkingAgainstHead(stashed);
- assertEquals(2, diffs.size());
- assertEquals(DiffEntry.ChangeType.DELETE, diffs.get(0).getChangeType());
- assertEquals("file.txt", diffs.get(0).getOldPath());
- assertEquals(DiffEntry.ChangeType.ADD, diffs.get(1).getChangeType());
- assertEquals("file2.txt", diffs.get(1).getNewPath());
- }
-
- @Test
- public void refLogIncludesCommitMessage() throws Exception {
- PersonIdent who = new PersonIdent("user", "user@email.com");
- deleteTrashFile("file.txt");
- RevCommit stashed = git.stashCreate().setPerson(who).call();
- assertNotNull(stashed);
- assertEquals("content", read(committedFile));
- validateStashedCommit(stashed);
-
- ReflogReader reader = git.getRepository().getReflogReader(
- Constants.R_STASH);
- ReflogEntry entry = reader.getLastEntry();
- assertNotNull(entry);
- assertEquals(ObjectId.zeroId(), entry.getOldId());
- assertEquals(stashed, entry.getNewId());
- assertEquals(who, entry.getWho());
- assertEquals(stashed.getFullMessage(), entry.getComment());
- }
-
- @Test(expected = UnmergedPathsException.class)
- public void unmergedPathsShouldCauseException() throws Exception {
- commitFile("file.txt", "master", "base");
- RevCommit side = commitFile("file.txt", "side", "side");
- commitFile("file.txt", "master", "master");
- git.merge().include(side).call();
-
- git.stashCreate().call();
- }
- }
|