/* * Copyright (C) 2021, Thomas Wolf and others * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0 which is available at * https://www.eclipse.org/org/documents/edl-v10.php. * * SPDX-License-Identifier: BSD-3-Clause */ package org.eclipse.jgit.lfs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.io.File; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ResetCommand.ResetType; import org.eclipse.jgit.attributes.FilterCommandRegistry; import org.eclipse.jgit.junit.RepositoryTestCase; import org.eclipse.jgit.lfs.lib.Constants; import org.eclipse.jgit.lib.StoredConfig; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; public class LfsGitTest extends RepositoryTestCase { private static final String SMUDGE_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + Constants.ATTR_FILTER_DRIVER_PREFIX + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_SMUDGE; private static final String CLEAN_NAME = org.eclipse.jgit.lib.Constants.BUILTIN_FILTER_PREFIX + Constants.ATTR_FILTER_DRIVER_PREFIX + org.eclipse.jgit.lib.Constants.ATTR_FILTER_TYPE_CLEAN; @BeforeClass public static void installLfs() { FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilter.FACTORY); FilterCommandRegistry.register(CLEAN_NAME, CleanFilter.FACTORY); } @AfterClass public static void removeLfs() { FilterCommandRegistry.unregister(SMUDGE_NAME); FilterCommandRegistry.unregister(CLEAN_NAME); } private Git git; @Override @Before public void setUp() throws Exception { super.setUp(); git = new Git(db); // commit something writeTrashFile("Test.txt", "Hello world"); git.add().addFilepattern("Test.txt").call(); git.commit().setMessage("Initial commit").call(); // prepare the config for LFS StoredConfig config = git.getRepository().getConfig(); config.setString("filter", "lfs", "clean", CLEAN_NAME); config.setString("filter", "lfs", "smudge", SMUDGE_NAME); config.save(); } @Test public void checkoutNonLfsPointer() throws Exception { String content = "size_t\nsome_function(void* ptr);\n"; File smallFile = writeTrashFile("Test.txt", content); StringBuilder largeContent = new StringBuilder( LfsPointer.SIZE_THRESHOLD * 4); while (largeContent.length() < LfsPointer.SIZE_THRESHOLD * 4) { largeContent.append(content); } File largeFile = writeTrashFile("large.txt", largeContent.toString()); fsTick(largeFile); git.add().addFilepattern("Test.txt").addFilepattern("large.txt").call(); git.commit().setMessage("Text files").call(); writeTrashFile(".gitattributes", "*.txt filter=lfs"); git.add().addFilepattern(".gitattributes").call(); git.commit().setMessage("attributes").call(); assertTrue(smallFile.delete()); assertTrue(largeFile.delete()); // This reset will run the two text files through the smudge filter git.reset().setMode(ResetType.HARD).call(); assertTrue(smallFile.exists()); assertTrue(largeFile.exists()); checkFile(smallFile, content); checkFile(largeFile, largeContent.toString()); // Modify the large file largeContent.append(content); writeTrashFile("large.txt", largeContent.toString()); // This should convert largeFile to an LFS pointer git.add().addFilepattern("large.txt").call(); git.commit().setMessage("Large modified").call(); String lfsPtr = "version https://git-lfs.github.com/spec/v1\n" + "oid sha256:d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614\n" + "size 858\n"; assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + "[Test.txt, mode:100644, content:" + content + ']' + "[large.txt, mode:100644, content:" + lfsPtr + ']', indexState(CONTENT)); // Verify the file has been saved File savedFile = new File(db.getDirectory(), "lfs"); savedFile = new File(savedFile, "objects"); savedFile = new File(savedFile, "d0"); savedFile = new File(savedFile, "41"); savedFile = new File(savedFile, "d041ab19bd7edd899b3c0450d0f61819f96672f0b22d26c9753abc62e1261614"); String saved = new String(Files.readAllBytes(savedFile.toPath()), StandardCharsets.UTF_8); assertEquals(saved, largeContent.toString()); assertTrue(smallFile.delete()); assertTrue(largeFile.delete()); git.reset().setMode(ResetType.HARD).call(); assertTrue(smallFile.exists()); assertTrue(largeFile.exists()); checkFile(smallFile, content); checkFile(largeFile, largeContent.toString()); assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + "[Test.txt, mode:100644, content:" + content + ']' + "[large.txt, mode:100644, content:" + lfsPtr + ']', indexState(CONTENT)); git.add().addFilepattern("Test.txt").call(); git.commit().setMessage("Small committed again").call(); String lfsPtrSmall = "version https://git-lfs.github.com/spec/v1\n" + "oid sha256:9110463275fb0e2f0e9fdeaf84e598e62915666161145cf08927079119cc7814\n" + "size 33\n"; assertEquals("[.gitattributes, mode:100644, content:*.txt filter=lfs]" + "[Test.txt, mode:100644, content:" + lfsPtrSmall + ']' + "[large.txt, mode:100644, content:" + lfsPtr + ']', indexState(CONTENT)); assertTrue(git.status().call().isClean()); } }