View Javadoc
1   /*
2    * Copyright (C) 2011, Robin Rosenberg
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  package org.eclipse.jgit.dircache;
44  
45  import static org.junit.Assert.assertEquals;
46  import static org.junit.Assert.fail;
47  
48  import java.util.ArrayList;
49  import java.util.List;
50  
51  import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
52  import org.eclipse.jgit.errors.DirCacheNameConflictException;
53  import org.eclipse.jgit.lib.FileMode;
54  import org.eclipse.jgit.lib.ObjectId;
55  import org.junit.Test;
56  
57  public class DirCachePathEditTest {
58  
59  	static final class AddEdit extends PathEdit {
60  
61  		public AddEdit(String entryPath) {
62  			super(entryPath);
63  		}
64  
65  		@Override
66  		public void apply(DirCacheEntry ent) {
67  			ent.setFileMode(FileMode.REGULAR_FILE);
68  			ent.setLength(1);
69  			ent.setObjectId(ObjectId.zeroId());
70  		}
71  
72  	}
73  
74  	private static final class RecordingEdit extends PathEdit {
75  		final List<DirCacheEntry> entries = new ArrayList<>();
76  
77  		public RecordingEdit(String entryPath) {
78  			super(entryPath);
79  		}
80  
81  		@Override
82  		public void apply(DirCacheEntry ent) {
83  			entries.add(ent);
84  		}
85  	}
86  
87  	@Test
88  	public void testAddDeletePathAndTreeNormalNames() {
89  		DirCache dc = DirCache.newInCore();
90  		DirCacheEditor editor = dc.editor();
91  		editor.add(new AddEdit("a"));
92  		editor.add(new AddEdit("b/c"));
93  		editor.add(new AddEdit("c/d"));
94  		editor.finish();
95  		assertEquals(3, dc.getEntryCount());
96  		assertEquals("a", dc.getEntry(0).getPathString());
97  		assertEquals("b/c", dc.getEntry(1).getPathString());
98  		assertEquals("c/d", dc.getEntry(2).getPathString());
99  
100 		editor = dc.editor();
101 		editor.add(new DirCacheEditor.DeletePath("b/c"));
102 		editor.finish();
103 		assertEquals(2, dc.getEntryCount());
104 		assertEquals("a", dc.getEntry(0).getPathString());
105 		assertEquals("c/d", dc.getEntry(1).getPathString());
106 
107 		editor = dc.editor();
108 		editor.add(new DirCacheEditor.DeleteTree(""));
109 		editor.finish();
110 		assertEquals(0, dc.getEntryCount());
111 	}
112 
113 	@Test
114 	public void testAddDeleteTrickyNames() {
115 		DirCache dc = DirCache.newInCore();
116 		DirCacheEditor editor = dc.editor();
117 		editor.add(new AddEdit("a/b"));
118 		editor.add(new AddEdit("a-"));
119 		editor.add(new AddEdit("ab"));
120 		editor.finish();
121 		assertEquals(3, dc.getEntryCount());
122 
123 		// Validate sort order
124 		assertEquals("a-", dc.getEntry(0).getPathString());
125 		assertEquals("a/b", dc.getEntry(1).getPathString());
126 		assertEquals("ab", dc.getEntry(2).getPathString());
127 
128 		editor = dc.editor();
129 
130 		// Sort order should not confuse DeleteTree
131 		editor.add(new DirCacheEditor.DeleteTree("a"));
132 		editor.finish();
133 		assertEquals(2, dc.getEntryCount());
134 		assertEquals("a-", dc.getEntry(0).getPathString());
135 		assertEquals("ab", dc.getEntry(1).getPathString());
136 	}
137 
138 	@Test
139 	public void testPathEditShouldBeCalledForEachStage() throws Exception {
140 		DirCache dc = DirCache.newInCore();
141 		DirCacheBuilder builder = new DirCacheBuilder(dc, 3);
142 		builder.add(createEntry("a", DirCacheEntry.STAGE_1));
143 		builder.add(createEntry("a", DirCacheEntry.STAGE_2));
144 		builder.add(createEntry("a", DirCacheEntry.STAGE_3));
145 		builder.finish();
146 
147 		DirCacheEditor editor = dc.editor();
148 		RecordingEdit recorder = new RecordingEdit("a");
149 		editor.add(recorder);
150 		editor.finish();
151 
152 		List<DirCacheEntry> entries = recorder.entries;
153 		assertEquals(3, entries.size());
154 		assertEquals(DirCacheEntry.STAGE_1, entries.get(0).getStage());
155 		assertEquals(DirCacheEntry.STAGE_2, entries.get(1).getStage());
156 		assertEquals(DirCacheEntry.STAGE_3, entries.get(2).getStage());
157 	}
158 
159 	@Test
160 	public void testFileReplacesTree() throws Exception {
161 		DirCache dc = DirCache.newInCore();
162 		DirCacheEditor editor = dc.editor();
163 		editor.add(new AddEdit("a"));
164 		editor.add(new AddEdit("b/c"));
165 		editor.add(new AddEdit("b/d"));
166 		editor.add(new AddEdit("e"));
167 		editor.finish();
168 
169 		editor = dc.editor();
170 		editor.add(new AddEdit("b"));
171 		editor.finish();
172 
173 		assertEquals(3, dc.getEntryCount());
174 		assertEquals("a", dc.getEntry(0).getPathString());
175 		assertEquals("b", dc.getEntry(1).getPathString());
176 		assertEquals("e", dc.getEntry(2).getPathString());
177 
178 		dc.clear();
179 		editor = dc.editor();
180 		editor.add(new AddEdit("A.c"));
181 		editor.add(new AddEdit("A/c"));
182 		editor.add(new AddEdit("A0c"));
183 		editor.finish();
184 
185 		editor = dc.editor();
186 		editor.add(new AddEdit("A"));
187 		editor.finish();
188 		assertEquals(3, dc.getEntryCount());
189 		assertEquals("A", dc.getEntry(0).getPathString());
190 		assertEquals("A.c", dc.getEntry(1).getPathString());
191 		assertEquals("A0c", dc.getEntry(2).getPathString());
192 	}
193 
194 	@Test
195 	public void testTreeReplacesFile() throws Exception {
196 		DirCache dc = DirCache.newInCore();
197 		DirCacheEditor editor = dc.editor();
198 		editor.add(new AddEdit("a"));
199 		editor.add(new AddEdit("ab"));
200 		editor.add(new AddEdit("b"));
201 		editor.add(new AddEdit("e"));
202 		editor.finish();
203 
204 		editor = dc.editor();
205 		editor.add(new AddEdit("b/c/d/f"));
206 		editor.add(new AddEdit("b/g/h/i"));
207 		editor.finish();
208 
209 		assertEquals(5, dc.getEntryCount());
210 		assertEquals("a", dc.getEntry(0).getPathString());
211 		assertEquals("ab", dc.getEntry(1).getPathString());
212 		assertEquals("b/c/d/f", dc.getEntry(2).getPathString());
213 		assertEquals("b/g/h/i", dc.getEntry(3).getPathString());
214 		assertEquals("e", dc.getEntry(4).getPathString());
215 	}
216 
217 	@Test
218 	public void testDuplicateFiles() throws Exception {
219 		DirCache dc = DirCache.newInCore();
220 		DirCacheEditor editor = dc.editor();
221 		editor.add(new AddEdit("a"));
222 		editor.add(new AddEdit("a"));
223 
224 		try {
225 			editor.finish();
226 			fail("Expected DirCacheNameConflictException to be thrown");
227 		} catch (DirCacheNameConflictException e) {
228 			assertEquals("a a", e.getMessage());
229 			assertEquals("a", e.getPath1());
230 			assertEquals("a", e.getPath2());
231 		}
232 	}
233 
234 	@Test
235 	public void testFileOverlapsTree() throws Exception {
236 		DirCache dc = DirCache.newInCore();
237 		DirCacheEditor editor = dc.editor();
238 		editor.add(new AddEdit("a"));
239 		editor.add(new AddEdit("a/b").setReplace(false));
240 		try {
241 			editor.finish();
242 			fail("Expected DirCacheNameConflictException to be thrown");
243 		} catch (DirCacheNameConflictException e) {
244 			assertEquals("a a/b", e.getMessage());
245 			assertEquals("a", e.getPath1());
246 			assertEquals("a/b", e.getPath2());
247 		}
248 
249 		editor = dc.editor();
250 		editor.add(new AddEdit("A.c"));
251 		editor.add(new AddEdit("A/c").setReplace(false));
252 		editor.add(new AddEdit("A0c"));
253 		editor.add(new AddEdit("A"));
254 		try {
255 			editor.finish();
256 			fail("Expected DirCacheNameConflictException to be thrown");
257 		} catch (DirCacheNameConflictException e) {
258 			assertEquals("A A/c", e.getMessage());
259 			assertEquals("A", e.getPath1());
260 			assertEquals("A/c", e.getPath2());
261 		}
262 
263 		editor = dc.editor();
264 		editor.add(new AddEdit("A.c"));
265 		editor.add(new AddEdit("A/b/c/d").setReplace(false));
266 		editor.add(new AddEdit("A/b/c"));
267 		editor.add(new AddEdit("A0c"));
268 		try {
269 			editor.finish();
270 			fail("Expected DirCacheNameConflictException to be thrown");
271 		} catch (DirCacheNameConflictException e) {
272 			assertEquals("A/b/c A/b/c/d", e.getMessage());
273 			assertEquals("A/b/c", e.getPath1());
274 			assertEquals("A/b/c/d", e.getPath2());
275 		}
276 	}
277 
278 	private static DirCacheEntry createEntry(String path, int stage) {
279 		DirCacheEntry entry = new DirCacheEntry(path, stage);
280 		entry.setFileMode(FileMode.REGULAR_FILE);
281 		return entry;
282 	}
283 }