View Javadoc
1   /*
2    * Copyright (C) 2011, 2020 Robin Rosenberg 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.dircache;
11  
12  import static org.junit.Assert.assertEquals;
13  import static org.junit.Assert.fail;
14  
15  import java.util.ArrayList;
16  import java.util.List;
17  
18  import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
19  import org.eclipse.jgit.errors.DirCacheNameConflictException;
20  import org.eclipse.jgit.lib.FileMode;
21  import org.eclipse.jgit.lib.ObjectId;
22  import org.junit.Test;
23  
24  public class DirCachePathEditTest {
25  
26  	static final class AddEdit extends PathEdit {
27  
28  		public AddEdit(String entryPath) {
29  			super(entryPath);
30  		}
31  
32  		@Override
33  		public void apply(DirCacheEntry ent) {
34  			ent.setFileMode(FileMode.REGULAR_FILE);
35  			ent.setLength(1);
36  			ent.setObjectId(ObjectId.zeroId());
37  		}
38  
39  	}
40  
41  	private static final class RecordingEdit extends PathEdit {
42  		final List<DirCacheEntry> entries = new ArrayList<>();
43  
44  		public RecordingEdit(String entryPath) {
45  			super(entryPath);
46  		}
47  
48  		@Override
49  		public void apply(DirCacheEntry ent) {
50  			entries.add(ent);
51  		}
52  	}
53  
54  	@Test
55  	public void testAddDeletePathAndTreeNormalNames() {
56  		DirCache dc = DirCache.newInCore();
57  		DirCacheEditor editor = dc.editor();
58  		editor.add(new AddEdit("a"));
59  		editor.add(new AddEdit("b/c"));
60  		editor.add(new AddEdit("c/d"));
61  		editor.finish();
62  		assertEquals(3, dc.getEntryCount());
63  		assertEquals("a", dc.getEntry(0).getPathString());
64  		assertEquals("b/c", dc.getEntry(1).getPathString());
65  		assertEquals("c/d", dc.getEntry(2).getPathString());
66  
67  		editor = dc.editor();
68  		editor.add(new DirCacheEditor.DeletePath("b/c"));
69  		editor.finish();
70  		assertEquals(2, dc.getEntryCount());
71  		assertEquals("a", dc.getEntry(0).getPathString());
72  		assertEquals("c/d", dc.getEntry(1).getPathString());
73  
74  		editor = dc.editor();
75  		editor.add(new DirCacheEditor.DeleteTree(""));
76  		editor.finish();
77  		assertEquals(0, dc.getEntryCount());
78  	}
79  
80  	@Test
81  	public void testAddDeleteTrickyNames() {
82  		DirCache dc = DirCache.newInCore();
83  		DirCacheEditor editor = dc.editor();
84  		editor.add(new AddEdit("a/b"));
85  		editor.add(new AddEdit("a-"));
86  		editor.add(new AddEdit("ab"));
87  		editor.finish();
88  		assertEquals(3, dc.getEntryCount());
89  
90  		// Validate sort order
91  		assertEquals("a-", dc.getEntry(0).getPathString());
92  		assertEquals("a/b", dc.getEntry(1).getPathString());
93  		assertEquals("ab", dc.getEntry(2).getPathString());
94  
95  		editor = dc.editor();
96  
97  		// Sort order should not confuse DeleteTree
98  		editor.add(new DirCacheEditor.DeleteTree("a"));
99  		editor.finish();
100 		assertEquals(2, dc.getEntryCount());
101 		assertEquals("a-", dc.getEntry(0).getPathString());
102 		assertEquals("ab", dc.getEntry(1).getPathString());
103 	}
104 
105 	@Test
106 	public void testPathEditShouldBeCalledForEachStage() throws Exception {
107 		DirCache dc = DirCache.newInCore();
108 		DirCacheBuilder builder = new DirCacheBuilder(dc, 3);
109 		builder.add(createEntry("a", DirCacheEntry.STAGE_1));
110 		builder.add(createEntry("a", DirCacheEntry.STAGE_2));
111 		builder.add(createEntry("a", DirCacheEntry.STAGE_3));
112 		builder.finish();
113 
114 		DirCacheEditor editor = dc.editor();
115 		RecordingEdit recorder = new RecordingEdit("a");
116 		editor.add(recorder);
117 		editor.finish();
118 
119 		List<DirCacheEntry> entries = recorder.entries;
120 		assertEquals(3, entries.size());
121 		assertEquals(DirCacheEntry.STAGE_1, entries.get(0).getStage());
122 		assertEquals(DirCacheEntry.STAGE_2, entries.get(1).getStage());
123 		assertEquals(DirCacheEntry.STAGE_3, entries.get(2).getStage());
124 	}
125 
126 	@Test
127 	public void testPathEditWithStagesAndReset() throws Exception {
128 		DirCache dc = DirCache.newInCore();
129 		DirCacheBuilder builder = new DirCacheBuilder(dc, 3);
130 		builder.add(createEntry("a", DirCacheEntry.STAGE_1));
131 		builder.add(createEntry("a", DirCacheEntry.STAGE_2));
132 		builder.add(createEntry("a", DirCacheEntry.STAGE_3));
133 		builder.finish();
134 
135 		DirCacheEditor editor = dc.editor();
136 		PathEdit edit = new PathEdit("a") {
137 
138 			@Override
139 			public void apply(DirCacheEntry ent) {
140 				ent.setStage(DirCacheEntry.STAGE_0);
141 			}
142 		};
143 		editor.add(edit);
144 		editor.finish();
145 
146 		assertEquals(1, dc.getEntryCount());
147 		DirCacheEntry entry = dc.getEntry(0);
148 		assertEquals("a", entry.getPathString());
149 		assertEquals(DirCacheEntry.STAGE_0, entry.getStage());
150 	}
151 
152 	@Test
153 	public void testFileReplacesTree() throws Exception {
154 		DirCache dc = DirCache.newInCore();
155 		DirCacheEditor editor = dc.editor();
156 		editor.add(new AddEdit("a"));
157 		editor.add(new AddEdit("b/c"));
158 		editor.add(new AddEdit("b/d"));
159 		editor.add(new AddEdit("e"));
160 		editor.finish();
161 
162 		editor = dc.editor();
163 		editor.add(new AddEdit("b"));
164 		editor.finish();
165 
166 		assertEquals(3, dc.getEntryCount());
167 		assertEquals("a", dc.getEntry(0).getPathString());
168 		assertEquals("b", dc.getEntry(1).getPathString());
169 		assertEquals("e", dc.getEntry(2).getPathString());
170 
171 		dc.clear();
172 		editor = dc.editor();
173 		editor.add(new AddEdit("A.c"));
174 		editor.add(new AddEdit("A/c"));
175 		editor.add(new AddEdit("A0c"));
176 		editor.finish();
177 
178 		editor = dc.editor();
179 		editor.add(new AddEdit("A"));
180 		editor.finish();
181 		assertEquals(3, dc.getEntryCount());
182 		assertEquals("A", dc.getEntry(0).getPathString());
183 		assertEquals("A.c", dc.getEntry(1).getPathString());
184 		assertEquals("A0c", dc.getEntry(2).getPathString());
185 	}
186 
187 	@Test
188 	public void testTreeReplacesFile() throws Exception {
189 		DirCache dc = DirCache.newInCore();
190 		DirCacheEditor editor = dc.editor();
191 		editor.add(new AddEdit("a"));
192 		editor.add(new AddEdit("ab"));
193 		editor.add(new AddEdit("b"));
194 		editor.add(new AddEdit("e"));
195 		editor.finish();
196 
197 		editor = dc.editor();
198 		editor.add(new AddEdit("b/c/d/f"));
199 		editor.add(new AddEdit("b/g/h/i"));
200 		editor.finish();
201 
202 		assertEquals(5, dc.getEntryCount());
203 		assertEquals("a", dc.getEntry(0).getPathString());
204 		assertEquals("ab", dc.getEntry(1).getPathString());
205 		assertEquals("b/c/d/f", dc.getEntry(2).getPathString());
206 		assertEquals("b/g/h/i", dc.getEntry(3).getPathString());
207 		assertEquals("e", dc.getEntry(4).getPathString());
208 	}
209 
210 	@Test
211 	public void testDuplicateFiles() throws Exception {
212 		DirCache dc = DirCache.newInCore();
213 		DirCacheEditor editor = dc.editor();
214 		editor.add(new AddEdit("a"));
215 		editor.add(new AddEdit("a"));
216 
217 		try {
218 			editor.finish();
219 			fail("Expected DirCacheNameConflictException to be thrown");
220 		} catch (DirCacheNameConflictException e) {
221 			assertEquals("a a", e.getMessage());
222 			assertEquals("a", e.getPath1());
223 			assertEquals("a", e.getPath2());
224 		}
225 	}
226 
227 	@Test
228 	public void testFileOverlapsTree() throws Exception {
229 		DirCache dc = DirCache.newInCore();
230 		DirCacheEditor editor = dc.editor();
231 		editor.add(new AddEdit("a"));
232 		editor.add(new AddEdit("a/b").setReplace(false));
233 		try {
234 			editor.finish();
235 			fail("Expected DirCacheNameConflictException to be thrown");
236 		} catch (DirCacheNameConflictException e) {
237 			assertEquals("a a/b", e.getMessage());
238 			assertEquals("a", e.getPath1());
239 			assertEquals("a/b", e.getPath2());
240 		}
241 
242 		editor = dc.editor();
243 		editor.add(new AddEdit("A.c"));
244 		editor.add(new AddEdit("A/c").setReplace(false));
245 		editor.add(new AddEdit("A0c"));
246 		editor.add(new AddEdit("A"));
247 		try {
248 			editor.finish();
249 			fail("Expected DirCacheNameConflictException to be thrown");
250 		} catch (DirCacheNameConflictException e) {
251 			assertEquals("A A/c", e.getMessage());
252 			assertEquals("A", e.getPath1());
253 			assertEquals("A/c", e.getPath2());
254 		}
255 
256 		editor = dc.editor();
257 		editor.add(new AddEdit("A.c"));
258 		editor.add(new AddEdit("A/b/c/d").setReplace(false));
259 		editor.add(new AddEdit("A/b/c"));
260 		editor.add(new AddEdit("A0c"));
261 		try {
262 			editor.finish();
263 			fail("Expected DirCacheNameConflictException to be thrown");
264 		} catch (DirCacheNameConflictException e) {
265 			assertEquals("A/b/c A/b/c/d", e.getMessage());
266 			assertEquals("A/b/c", e.getPath1());
267 			assertEquals("A/b/c/d", e.getPath2());
268 		}
269 	}
270 
271 	private static DirCacheEntry createEntry(String path, int stage) {
272 		DirCacheEntry entry = new DirCacheEntry(path, stage);
273 		entry.setFileMode(FileMode.REGULAR_FILE);
274 		return entry;
275 	}
276 }