mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-14 01:15:44 +01:00
Merged in feature/migrate_lfs (pull request #275)
Migrate git LFS blob directory
This commit is contained in:
@@ -0,0 +1,15 @@
|
|||||||
|
package sonia.scm.update;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public interface BlobDirectoryAccess {
|
||||||
|
|
||||||
|
void forBlobDirectories(BlobDirectoryConsumer blobDirectoryConsumer) throws IOException;
|
||||||
|
|
||||||
|
void moveToRepositoryBlobStore(Path blobDirectory, String newDirectoryName, String repositoryId) throws IOException;
|
||||||
|
|
||||||
|
interface BlobDirectoryConsumer {
|
||||||
|
void accept(Path directory) throws IOException;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
package sonia.scm.store;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import sonia.scm.SCMContextProvider;
|
||||||
|
import sonia.scm.repository.RepositoryLocationResolver;
|
||||||
|
import sonia.scm.update.BlobDirectoryAccess;
|
||||||
|
import sonia.scm.util.IOUtil;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class DefaultBlobDirectoryAccess implements BlobDirectoryAccess {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(DefaultBlobDirectoryAccess.class);
|
||||||
|
|
||||||
|
private final SCMContextProvider contextProvider;
|
||||||
|
private final RepositoryLocationResolver locationResolver;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DefaultBlobDirectoryAccess(SCMContextProvider contextProvider, RepositoryLocationResolver locationResolver) {
|
||||||
|
this.contextProvider = contextProvider;
|
||||||
|
this.locationResolver = locationResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void forBlobDirectories(BlobDirectoryConsumer blobDirectoryConsumer) throws IOException {
|
||||||
|
Path v1blobDir = computeV1BlobDir();
|
||||||
|
if (Files.exists(v1blobDir) && Files.isDirectory(v1blobDir)) {
|
||||||
|
try (Stream<Path> fileStream = Files.list(v1blobDir)) {
|
||||||
|
fileStream.filter(p -> Files.isDirectory(p)).forEach(p -> {
|
||||||
|
try {
|
||||||
|
blobDirectoryConsumer.accept(p);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("could not call consumer for blob directory " + p, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveToRepositoryBlobStore(Path blobDirectory, String newDirectoryName, String repositoryId) throws IOException {
|
||||||
|
Path repositoryLocation;
|
||||||
|
try {
|
||||||
|
repositoryLocation = locationResolver
|
||||||
|
.forClass(Path.class)
|
||||||
|
.getLocation(repositoryId);
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
LOG.info("ignoring blob directory {} because there is no repository location for repository id {}", blobDirectory, repositoryId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Path target = repositoryLocation
|
||||||
|
.resolve(Store.BLOB.getRepositoryStoreDirectory());
|
||||||
|
IOUtil.mkdirs(target.toFile());
|
||||||
|
Path resolvedSourceDirectory = computeV1BlobDir().resolve(blobDirectory);
|
||||||
|
Path resolvedTargetDirectory = target.resolve(newDirectoryName);
|
||||||
|
LOG.trace("moving directory {} to {}", resolvedSourceDirectory, resolvedTargetDirectory);
|
||||||
|
Files.move(resolvedSourceDirectory, resolvedTargetDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Path computeV1BlobDir() {
|
||||||
|
return contextProvider.getBaseDirectory().toPath().resolve("var").resolve("blob");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,6 @@ public class JAXBPropertyFileAccess implements PropertyFileAccess {
|
|||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JAXBPropertyFileAccess.class);
|
private static final Logger LOG = LoggerFactory.getLogger(JAXBPropertyFileAccess.class);
|
||||||
|
|
||||||
public static final String XML_FILENAME_SUFFIX = ".xml";
|
|
||||||
private final SCMContextProvider contextProvider;
|
private final SCMContextProvider contextProvider;
|
||||||
private final RepositoryLocationResolver locationResolver;
|
private final RepositoryLocationResolver locationResolver;
|
||||||
|
|
||||||
@@ -31,8 +30,8 @@ public class JAXBPropertyFileAccess implements PropertyFileAccess {
|
|||||||
public Target renameGlobalConfigurationFrom(String oldName) {
|
public Target renameGlobalConfigurationFrom(String oldName) {
|
||||||
return newName -> {
|
return newName -> {
|
||||||
Path configDir = contextProvider.getBaseDirectory().toPath().resolve(StoreConstants.CONFIG_DIRECTORY_NAME);
|
Path configDir = contextProvider.getBaseDirectory().toPath().resolve(StoreConstants.CONFIG_DIRECTORY_NAME);
|
||||||
Path oldConfigFile = configDir.resolve(oldName + XML_FILENAME_SUFFIX);
|
Path oldConfigFile = configDir.resolve(oldName + StoreConstants.FILE_EXTENSION);
|
||||||
Path newConfigFile = configDir.resolve(newName + XML_FILENAME_SUFFIX);
|
Path newConfigFile = configDir.resolve(newName + StoreConstants.FILE_EXTENSION);
|
||||||
Files.move(oldConfigFile, newConfigFile);
|
Files.move(oldConfigFile, newConfigFile);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -45,7 +44,7 @@ public class JAXBPropertyFileAccess implements PropertyFileAccess {
|
|||||||
Path v1storeDir = computeV1StoreDir();
|
Path v1storeDir = computeV1StoreDir();
|
||||||
if (Files.exists(v1storeDir) && Files.isDirectory(v1storeDir)) {
|
if (Files.exists(v1storeDir) && Files.isDirectory(v1storeDir)) {
|
||||||
try (Stream<Path> fileStream = Files.list(v1storeDir)) {
|
try (Stream<Path> fileStream = Files.list(v1storeDir)) {
|
||||||
fileStream.filter(p -> p.toString().endsWith(XML_FILENAME_SUFFIX)).forEach(p -> {
|
fileStream.filter(p -> p.toString().endsWith(StoreConstants.FILE_EXTENSION)).forEach(p -> {
|
||||||
try {
|
try {
|
||||||
String storeName = extractStoreName(p);
|
String storeName = extractStoreName(p);
|
||||||
storeFileConsumer.accept(p, storeName);
|
storeFileConsumer.accept(p, storeName);
|
||||||
@@ -84,7 +83,7 @@ public class JAXBPropertyFileAccess implements PropertyFileAccess {
|
|||||||
|
|
||||||
private String extractStoreName(Path p) {
|
private String extractStoreName(Path p) {
|
||||||
String fileName = p.getFileName().toString();
|
String fileName = p.getFileName().toString();
|
||||||
return fileName.substring(0, fileName.length() - XML_FILENAME_SUFFIX.length());
|
return fileName.substring(0, fileName.length() - StoreConstants.FILE_EXTENSION.length());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package sonia.scm.web.lfs;
|
||||||
|
|
||||||
|
import sonia.scm.migration.UpdateStep;
|
||||||
|
import sonia.scm.plugin.Extension;
|
||||||
|
import sonia.scm.update.BlobDirectoryAccess;
|
||||||
|
import sonia.scm.version.Version;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class LfsV1UpdateStep implements UpdateStep {
|
||||||
|
|
||||||
|
private final BlobDirectoryAccess blobDirectoryAccess;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public LfsV1UpdateStep(BlobDirectoryAccess blobDirectoryAccess) {
|
||||||
|
this.blobDirectoryAccess = blobDirectoryAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doUpdate() throws Exception {
|
||||||
|
blobDirectoryAccess.forBlobDirectories(
|
||||||
|
f -> {
|
||||||
|
Path v1Directory = f.getFileName();
|
||||||
|
String v1DirectoryName = v1Directory.toString();
|
||||||
|
if (v1DirectoryName.endsWith("-git-lfs")) {
|
||||||
|
blobDirectoryAccess.moveToRepositoryBlobStore(f, v1DirectoryName, v1DirectoryName.substring(0, v1DirectoryName.length() - "-git-lfs".length()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Version getTargetVersion() {
|
||||||
|
return Version.parse("2.0.0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAffectedDataType() {
|
||||||
|
return "sonia.scm.git.lfs";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,11 +19,13 @@ import sonia.scm.store.BlobStoreFactory;
|
|||||||
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
import sonia.scm.store.ConfigurationEntryStoreFactory;
|
||||||
import sonia.scm.store.ConfigurationStoreFactory;
|
import sonia.scm.store.ConfigurationStoreFactory;
|
||||||
import sonia.scm.store.DataStoreFactory;
|
import sonia.scm.store.DataStoreFactory;
|
||||||
|
import sonia.scm.store.DefaultBlobDirectoryAccess;
|
||||||
import sonia.scm.store.FileBlobStoreFactory;
|
import sonia.scm.store.FileBlobStoreFactory;
|
||||||
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
import sonia.scm.store.JAXBConfigurationEntryStoreFactory;
|
||||||
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
import sonia.scm.store.JAXBConfigurationStoreFactory;
|
||||||
import sonia.scm.store.JAXBDataStoreFactory;
|
import sonia.scm.store.JAXBDataStoreFactory;
|
||||||
import sonia.scm.store.JAXBPropertyFileAccess;
|
import sonia.scm.store.JAXBPropertyFileAccess;
|
||||||
|
import sonia.scm.update.BlobDirectoryAccess;
|
||||||
import sonia.scm.update.PropertyFileAccess;
|
import sonia.scm.update.PropertyFileAccess;
|
||||||
import sonia.scm.update.V1PropertyDAO;
|
import sonia.scm.update.V1PropertyDAO;
|
||||||
import sonia.scm.update.xml.XmlV1PropertyDAO;
|
import sonia.scm.update.xml.XmlV1PropertyDAO;
|
||||||
@@ -65,6 +67,7 @@ public class BootstrapModule extends AbstractModule {
|
|||||||
bind(PluginLoader.class).toInstance(pluginLoader);
|
bind(PluginLoader.class).toInstance(pluginLoader);
|
||||||
bind(V1PropertyDAO.class, XmlV1PropertyDAO.class);
|
bind(V1PropertyDAO.class, XmlV1PropertyDAO.class);
|
||||||
bind(PropertyFileAccess.class, JAXBPropertyFileAccess.class);
|
bind(PropertyFileAccess.class, JAXBPropertyFileAccess.class);
|
||||||
|
bind(BlobDirectoryAccess.class, DefaultBlobDirectoryAccess.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T> void bind(Class<T> clazz, Class<? extends T> defaultImplementation) {
|
private <T> void bind(Class<T> clazz, Class<? extends T> defaultImplementation) {
|
||||||
|
|||||||
Reference in New Issue
Block a user