| /* | |
| * Copyright (C) 2022, Matthias Fromme <mfromme@dspace.de> | |
| * | |
| * 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.io.IOException; | |
| import java.io.InputStream; | |
| import java.io.OutputStream; | |
| import java.util.ArrayList; | |
| import java.util.List; | |
| import org.eclipse.jgit.api.Git; | |
| import org.eclipse.jgit.api.ResetCommand.ResetType; | |
| import org.eclipse.jgit.attributes.FilterCommand; | |
| import org.eclipse.jgit.attributes.FilterCommandRegistry; | |
| import org.eclipse.jgit.junit.RepositoryTestCase; | |
| import org.eclipse.jgit.lfs.internal.LfsConnectionFactory; | |
| import org.eclipse.jgit.lfs.lib.Constants; | |
| import org.eclipse.jgit.lib.ConfigConstants; | |
| import org.eclipse.jgit.lib.Repository; | |
| import org.eclipse.jgit.lib.StoredConfig; | |
| import org.eclipse.jgit.transport.http.HttpConnection; | |
| import org.eclipse.jgit.util.HttpSupport; | |
| import org.junit.AfterClass; | |
| import org.junit.Before; | |
| import org.junit.BeforeClass; | |
| import org.junit.Test; | |
| /** | |
| * Test if the lfs config is used in the correct way during checkout. | |
| * | |
| * Two lfs-files are created, one that comes before .gitattributes and | |
| * .lfsconfig in git order (".aaa.txt") and one that comes after ("zzz.txt"). | |
| * | |
| * During checkout/reset it is tested if the correct version of the lfs config | |
| * is used. | |
| * | |
| * TODO: The current behavior seems a little bit strange/unintuitive. Some files | |
| * are checked out before and some after the config files. This leads to the | |
| * behavior, that during a single command the config changes. Since this seems | |
| * to be the same way in native git, the behavior is accepted for now. | |
| * | |
| */ | |
| public class LfsConfigGitTest 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 LFS_SERVER_URI1 = "https://lfs.server1/test/uri"; | |
| private static final String EXPECTED_SERVER_URL1 = LFS_SERVER_URI1 | |
| + Protocol.OBJECTS_LFS_ENDPOINT; | |
| private static final String LFS_SERVER_URI2 = "https://lfs.server2/test/uri"; | |
| private static final String EXPECTED_SERVER_URL2 = LFS_SERVER_URI2 | |
| + Protocol.OBJECTS_LFS_ENDPOINT; | |
| private static final String LFS_SERVER_URI3 = "https://lfs.server3/test/uri"; | |
| private static final String EXPECTED_SERVER_URL3 = LFS_SERVER_URI3 | |
| + Protocol.OBJECTS_LFS_ENDPOINT; | |
| private static final String FAKE_LFS_POINTER1 = "version https://git-lfs.github.com/spec/v1\n" | |
| + "oid sha256:6ce9fab52ee9a6c4c097def4e049c6acdeba44c99d26e83ba80adec1473c9b2d\n" | |
| + "size 253952\n"; | |
| private static final String FAKE_LFS_POINTER2 = "version https://git-lfs.github.com/spec/v1\n" | |
| + "oid sha256:a4b711cd989863ae2038758a62672138347abbbae4076a7ad3a545fda7d08f82\n" | |
| + "size 67072\n"; | |
| private static List<String> checkoutURLs = new ArrayList<>(); | |
| static class SmudgeFilterMock extends FilterCommand { | |
| public SmudgeFilterMock(Repository db, InputStream in, | |
| OutputStream out) throws IOException { | |
| super(in, out); | |
| HttpConnection lfsServerConn = LfsConnectionFactory.getLfsConnection(db, | |
| HttpSupport.METHOD_POST, Protocol.OPERATION_DOWNLOAD); | |
| checkoutURLs.add(lfsServerConn.getURL().toString()); | |
| } | |
| @Override | |
| public int run() throws IOException { | |
| // Stupid no impl | |
| in.transferTo(out); | |
| return -1; | |
| } | |
| } | |
| @BeforeClass | |
| public static void installLfs() { | |
| FilterCommandRegistry.register(SMUDGE_NAME, SmudgeFilterMock::new); | |
| } | |
| @AfterClass | |
| public static void removeLfs() { | |
| FilterCommandRegistry.unregister(SMUDGE_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", "smudge", SMUDGE_NAME); | |
| config.setString(ConfigConstants.CONFIG_CORE_SECTION, null, | |
| ConfigConstants.CONFIG_KEY_AUTOCRLF, "false"); | |
| config.save(); | |
| fileBefore = null; | |
| fileAfter = null; | |
| configFile = null; | |
| gitAttributesFile = null; | |
| } | |
| File fileBefore; | |
| File fileAfter; | |
| File configFile; | |
| File gitAttributesFile; | |
| private void createLfsFiles(String lfsPointer) throws Exception { | |
| //File to be checked out before lfs config | |
| String fileNameBefore = ".aaa.txt"; | |
| fileBefore = writeTrashFile(fileNameBefore, lfsPointer); | |
| git.add().addFilepattern(fileNameBefore).call(); | |
| // File to be checked out after lfs config | |
| String fileNameAfter = "zzz.txt"; | |
| fileAfter = writeTrashFile(fileNameAfter, lfsPointer); | |
| git.add().addFilepattern(fileNameAfter).call(); | |
| git.commit().setMessage("Commit LFS Pointer files").call(); | |
| } | |
| private String addLfsConfigFiles(String lfsServerUrl) throws Exception { | |
| // Add config files to the repo | |
| String lfsConfig1 = createLfsConfig(lfsServerUrl); | |
| git.add().addFilepattern(Constants.DOT_LFS_CONFIG).call(); | |
| // Modify gitattributes on second call, to force checkout too. | |
| if (gitAttributesFile == null) { | |
| gitAttributesFile = writeTrashFile(".gitattributes", | |
| "*.txt filter=lfs"); | |
| } else { | |
| gitAttributesFile = writeTrashFile(".gitattributes", | |
| "*.txt filter=lfs\n"); | |
| } | |
| git.add().addFilepattern(".gitattributes").call(); | |
| git.commit().setMessage("Commit config files").call(); | |
| return lfsConfig1; | |
| } | |
| private String createLfsConfig(String lfsServerUrl) throws IOException { | |
| String lfsConfig1 = "[lfs]\n url = " + lfsServerUrl; | |
| configFile = writeTrashFile(Constants.DOT_LFS_CONFIG, lfsConfig1); | |
| return lfsConfig1; | |
| } | |
| @Test | |
| public void checkoutLfsObjects_reset() throws Exception { | |
| createLfsFiles(FAKE_LFS_POINTER1); | |
| String lfsConfig1 = addLfsConfigFiles(LFS_SERVER_URI1); | |
| // Delete files to force action on reset | |
| assertTrue(configFile.delete()); | |
| assertTrue(fileBefore.delete()); | |
| assertTrue(fileAfter.delete()); | |
| assertTrue(gitAttributesFile.delete()); | |
| // create config file with different url | |
| createLfsConfig(LFS_SERVER_URI3); | |
| checkoutURLs.clear(); | |
| git.reset().setMode(ResetType.HARD).call(); | |
| checkFile(configFile, lfsConfig1); | |
| checkFile(fileBefore, FAKE_LFS_POINTER1); | |
| checkFile(fileAfter, FAKE_LFS_POINTER1); | |
| assertEquals(2, checkoutURLs.size()); | |
| // TODO: Should may be EXPECTED_SERVR_URL1 | |
| assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); | |
| assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(1)); | |
| } | |
| @Test | |
| public void checkoutLfsObjects_BranchSwitch() throws Exception { | |
| // Create a new branch "URL1" and add config files | |
| git.checkout().setCreateBranch(true).setName("URL1").call(); | |
| createLfsFiles(FAKE_LFS_POINTER1); | |
| String lfsConfig1 = addLfsConfigFiles(LFS_SERVER_URI1); | |
| // Create a second new branch "URL2" and add config files | |
| git.checkout().setCreateBranch(true).setName("URL2").call(); | |
| createLfsFiles(FAKE_LFS_POINTER2); | |
| String lfsConfig2 = addLfsConfigFiles(LFS_SERVER_URI2); | |
| checkFile(configFile, lfsConfig2); | |
| checkFile(fileBefore, FAKE_LFS_POINTER2); | |
| checkFile(fileAfter, FAKE_LFS_POINTER2); | |
| checkoutURLs.clear(); | |
| git.checkout().setName("URL1").call(); | |
| checkFile(configFile, lfsConfig1); | |
| checkFile(fileBefore, FAKE_LFS_POINTER1); | |
| checkFile(fileAfter, FAKE_LFS_POINTER1); | |
| assertEquals(2, checkoutURLs.size()); | |
| // TODO: Should may be EXPECTED_SERVR_URL1 | |
| assertEquals(EXPECTED_SERVER_URL2, checkoutURLs.get(0)); | |
| assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(1)); | |
| checkoutURLs.clear(); | |
| git.checkout().setName("URL2").call(); | |
| checkFile(configFile, lfsConfig2); | |
| checkFile(fileBefore, FAKE_LFS_POINTER2); | |
| checkFile(fileAfter, FAKE_LFS_POINTER2); | |
| assertEquals(2, checkoutURLs.size()); | |
| // TODO: Should may be EXPECTED_SERVR_URL2 | |
| assertEquals(EXPECTED_SERVER_URL1, checkoutURLs.get(0)); | |
| assertEquals(EXPECTED_SERVER_URL2, checkoutURLs.get(1)); | |
| } | |
| @Test | |
| public void checkoutLfsObjects_BranchSwitch_ModifiedLocal() | |
| throws Exception { | |
| // Create a new branch "URL1" and add config files | |
| git.checkout().setCreateBranch(true).setName("URL1").call(); | |
| createLfsFiles(FAKE_LFS_POINTER1); | |
| addLfsConfigFiles(LFS_SERVER_URI1); | |
| // Create a second new branch "URL2" and add config files | |
| git.checkout().setCreateBranch(true).setName("URL2").call(); | |
| createLfsFiles(FAKE_LFS_POINTER2); | |
| addLfsConfigFiles(LFS_SERVER_URI1); | |
| // create config file with different url | |
| assertTrue(configFile.delete()); | |
| String lfsConfig3 = createLfsConfig(LFS_SERVER_URI3); | |
| checkFile(configFile, lfsConfig3); | |
| checkFile(fileBefore, FAKE_LFS_POINTER2); | |
| checkFile(fileAfter, FAKE_LFS_POINTER2); | |
| checkoutURLs.clear(); | |
| git.checkout().setName("URL1").call(); | |
| checkFile(fileBefore, FAKE_LFS_POINTER1); | |
| checkFile(fileAfter, FAKE_LFS_POINTER1); | |
| checkFile(configFile, lfsConfig3); | |
| assertEquals(2, checkoutURLs.size()); | |
| assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); | |
| assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(1)); | |
| checkoutURLs.clear(); | |
| git.checkout().setName("URL2").call(); | |
| checkFile(fileBefore, FAKE_LFS_POINTER2); | |
| checkFile(fileAfter, FAKE_LFS_POINTER2); | |
| checkFile(configFile, lfsConfig3); | |
| assertEquals(2, checkoutURLs.size()); | |
| assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(0)); | |
| assertEquals(EXPECTED_SERVER_URL3, checkoutURLs.get(1)); | |
| } | |
| } |