xref: /JGit/org.eclipse.jgit.lfs.test/tst/org/eclipse/jgit/lfs/LfsGitTest.java (revision 616a88895dfc36fd3c9fea7d010b03e6d2cf8c1d)
1*616a8889SThomas Wolf /*
2*616a8889SThomas Wolf  * Copyright (C) 2021, Thomas Wolf <thomas.wolf@paranor.ch> and others
3*616a8889SThomas Wolf  *
4*616a8889SThomas Wolf  * This program and the accompanying materials are made available under the
5*616a8889SThomas Wolf  * terms of the Eclipse Distribution License v. 1.0 which is available at
6*616a8889SThomas Wolf  * https://www.eclipse.org/org/documents/edl-v10.php.
7*616a8889SThomas Wolf  *
8*616a8889SThomas Wolf  * SPDX-License-Identifier: BSD-3-Clause
9*616a8889SThomas Wolf  */
10*616a8889SThomas Wolf package org.eclipse.jgit.lfs;
11*616a8889SThomas Wolf 
12*616a8889SThomas Wolf import static org.junit.Assert.assertEquals;
13*616a8889SThomas Wolf import static org.junit.Assert.assertTrue;
14*616a8889SThomas Wolf 
15*616a8889SThomas Wolf import java.io.File;
16*616a8889SThomas Wolf import java.nio.charset.StandardCharsets;
17*616a8889SThomas Wolf import java.nio.file.Files;
18*616a8889SThomas Wolf 
19*616a8889SThomas Wolf import org.eclipse.jgit.api.Git;
20*616a8889SThomas Wolf import org.eclipse.jgit.api.ResetCommand.ResetType;
21*616a8889SThomas Wolf import org.eclipse.jgit.attributes.FilterCommandRegistry;
22*616a8889SThomas Wolf import org.eclipse.jgit.junit.RepositoryTestCase;
23*616a8889SThomas Wolf import org.eclipse.jgit.lfs.lib.Constants;
24*616a8889SThomas Wolf import org.eclipse.jgit.lib.StoredConfig;
25*616a8889SThomas Wolf import org.junit.AfterClass;
26*616a8889SThomas Wolf import org.junit.Before;
27*616a8889SThomas Wolf import org.junit.BeforeClass;
28*616a8889SThomas Wolf import org.junit.Test;
29*616a8889SThomas Wolf 
30*616a8889SThomas Wolf public class LfsGitTest extends RepositoryTestCase {
31*616a8889SThomas Wolf 
32*616a8889SThomas Wolf 	private static final String SMUDGE_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX
33*616a8889SThomas Wolf 			+ Constants.ATTR_FILTER_DRIVER_PREFIX
34*616a8889SThomas Wolf 			+ org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_SMUDGE;
35*616a8889SThomas Wolf 
36*616a8889SThomas Wolf 	private static final String CLEAN_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX
37*616a8889SThomas Wolf 			+ Constants.ATTR_FILTER_DRIVER_PREFIX
38*616a8889SThomas Wolf 			+ org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_CLEAN;
39*616a8889SThomas Wolf 
40*616a8889SThomas Wolf 	@BeforeClass
installLfs()41*616a8889SThomas Wolf 	public static void installLfs() {
42*616a8889SThomas Wolf 		FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilter.FACTORY);
43*616a8889SThomas Wolf 		FilterCommandRegistry.register(CLEAN_NAME, CleanFilter.FACTORY);
44*616a8889SThomas Wolf 	}
45*616a8889SThomas Wolf 
46*616a8889SThomas Wolf 	@AfterClass
removeLfs()47*616a8889SThomas Wolf 	public static void removeLfs() {
48*616a8889SThomas Wolf 		FilterCommandRegistry.unregister(SMUDGE_NAME);
49*616a8889SThomas Wolf 		FilterCommandRegistry.unregister(CLEAN_NAME);
50*616a8889SThomas Wolf 	}
51*616a8889SThomas Wolf 
52*616a8889SThomas Wolf 	private Git git;
53*616a8889SThomas Wolf 
54*616a8889SThomas Wolf 	@Override
55*616a8889SThomas Wolf 	@Before
setUp()56*616a8889SThomas Wolf 	public void setUp() throws Exception {
57*616a8889SThomas Wolf 		super.setUp();
58*616a8889SThomas Wolf 		git = new Git(db);
59*616a8889SThomas Wolf 		// commit something
60*616a8889SThomas Wolf 		writeTrashFile("Test.txt", "Hello world");
61*616a8889SThomas Wolf 		git.add().addFilepattern("Test.txt").call();
62*616a8889SThomas Wolf 		git.commit().setMessage("Initial commit").call();
63*616a8889SThomas Wolf 		// prepare the config for LFS
64*616a8889SThomas Wolf 		StoredConfig config = git.getRepository().getConfig();
65*616a8889SThomas Wolf 		config.setString("filter", "lfs", "clean", CLEAN_NAME);
66*616a8889SThomas Wolf 		config.setString("filter", "lfs", "smudge", SMUDGE_NAME);
67*616a8889SThomas Wolf 		config.save();
68*616a8889SThomas Wolf 	}
69*616a8889SThomas Wolf 
70*616a8889SThomas Wolf 	@Test
checkoutNonLfsPointer()71*616a8889SThomas Wolf 	public void checkoutNonLfsPointer() throws Exception {
72*616a8889SThomas Wolf 		String content = "size_t\nsome_function(void* ptr);\n";
73*616a8889SThomas Wolf 		File smallFile = writeTrashFile("Test.txt", content);
74*616a8889SThomas Wolf 		StringBuilder largeContent = new StringBuilder(
75*616a8889SThomas Wolf 				LfsPointer.SIZE_THRESHOLD * 4);
76*616a8889SThomas Wolf 		while (largeContent.length() < LfsPointer.SIZE_THRESHOLD * 4) {
77*616a8889SThomas Wolf 			largeContent.append(content);
78*616a8889SThomas Wolf 		}
79*616a8889SThomas Wolf 		File largeFile = writeTrashFile("large.txt", largeContent.toString());
80*616a8889SThomas Wolf 		fsTick(largeFile);
81*616a8889SThomas Wolf 		git.add().addFilepattern("Test.txt").addFilepattern("large.txt").call();
82*616a8889SThomas Wolf 		git.commit().setMessage("Text files").call();
83*616a8889SThomas Wolf 		writeTrashFile(".gitattributes", "*.txt filter=lfs");
84*616a8889SThomas Wolf 		git.add().addFilepattern(".gitattributes").call();
85*616a8889SThomas Wolf 		git.commit().setMessage("attributes").call();
86*616a8889SThomas Wolf 		assertTrue(smallFile.delete());
87*616a8889SThomas Wolf 		assertTrue(largeFile.delete());
88*616a8889SThomas Wolf 		// This reset will run the two text files through the smudge filter
89*616a8889SThomas Wolf 		git.reset().setMode(ResetType.HARD).call();
90*616a8889SThomas Wolf 		assertTrue(smallFile.exists());
91*616a8889SThomas Wolf 		assertTrue(largeFile.exists());
92*616a8889SThomas Wolf 		checkFile(smallFile, content);
93*616a8889SThomas Wolf 		checkFile(largeFile, largeContent.toString());
94*616a8889SThomas Wolf 		// Modify the large file
95*616a8889SThomas Wolf 		largeContent.append(content);
96*616a8889SThomas Wolf 		writeTrashFile("large.txt", largeContent.toString());
97*616a8889SThomas Wolf 		// This should convert largeFile to an LFS pointer
98*616a8889SThomas Wolf 		git.add().addFilepattern("large.txt").call();
99*616a8889SThomas Wolf 		git.commit().setMessage("Large modified").call();
100*616a8889SThomas Wolf 		String lfsPtr = "version https://git-lfs.github.com/spec/v1\n"
101*616a8889SThomas Wolf 				+ "oid sha256:d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614\n"
102*616a8889SThomas Wolf 				+ "size 858\n";
103*616a8889SThomas Wolf 		assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]"
104*616a8889SThomas Wolf 				+ "[Test.txt, mode:100644, content:" + content + ']'
105*616a8889SThomas Wolf 						+ "[large.txt, mode:100644, content:" + lfsPtr + ']',
106*616a8889SThomas Wolf 				indexState(CONTENT));
107*616a8889SThomas Wolf 		// Verify the file has been saved
108*616a8889SThomas Wolf 		File savedFile = new File(db.getDirectory(), "lfs");
109*616a8889SThomas Wolf 		savedFile = new File(savedFile, "objects");
110*616a8889SThomas Wolf 		savedFile = new File(savedFile, "d0");
111*616a8889SThomas Wolf 		savedFile = new File(savedFile, "41");
112*616a8889SThomas Wolf 		savedFile = new File(savedFile,
113*616a8889SThomas Wolf 				"d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614");
114*616a8889SThomas Wolf 		String saved = new String(Files.readAllBytes(savedFile.toPath()),
115*616a8889SThomas Wolf 				StandardCharsets.UTF_8);
116*616a8889SThomas Wolf 		assertEquals(saved, largeContent.toString());
117*616a8889SThomas Wolf 
118*616a8889SThomas Wolf 		assertTrue(smallFile.delete());
119*616a8889SThomas Wolf 		assertTrue(largeFile.delete());
120*616a8889SThomas Wolf 		git.reset().setMode(ResetType.HARD).call();
121*616a8889SThomas Wolf 		assertTrue(smallFile.exists());
122*616a8889SThomas Wolf 		assertTrue(largeFile.exists());
123*616a8889SThomas Wolf 		checkFile(smallFile, content);
124*616a8889SThomas Wolf 		checkFile(largeFile, largeContent.toString());
125*616a8889SThomas Wolf 		assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]"
126*616a8889SThomas Wolf 				+ "[Test.txt, mode:100644, content:" + content + ']'
127*616a8889SThomas Wolf 						+ "[large.txt, mode:100644, content:" + lfsPtr + ']',
128*616a8889SThomas Wolf 				indexState(CONTENT));
129*616a8889SThomas Wolf 		git.add().addFilepattern("Test.txt").call();
130*616a8889SThomas Wolf 		git.commit().setMessage("Small committed again").call();
131*616a8889SThomas Wolf 		String lfsPtrSmall = "version https://git-lfs.github.com/spec/v1\n"
132*616a8889SThomas Wolf 				+ "oid sha256:9110463275fb0e2f0e9fdeaf84e598e62915666161145cf08927079119cc7814\n"
133*616a8889SThomas Wolf 				+ "size 33\n";
134*616a8889SThomas Wolf 		assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]"
135*616a8889SThomas Wolf 				+ "[Test.txt, mode:100644, content:" + lfsPtrSmall + ']'
136*616a8889SThomas Wolf 						+ "[large.txt, mode:100644, content:" + lfsPtr + ']',
137*616a8889SThomas Wolf 				indexState(CONTENT));
138*616a8889SThomas Wolf 
139*616a8889SThomas Wolf 		assertTrue(git.status().call().isClean());
140*616a8889SThomas Wolf 	}
141*616a8889SThomas Wolf }
142