Merged in feature/migrate_lfs (pull request #275)

Migrate git LFS blob directory
This commit is contained in:
Eduard Heimbuch
2019-07-04 12:24:45 +00:00
5 changed files with 133 additions and 5 deletions

View File

@@ -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;
}
}

View File

@@ -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");
}
}

View File

@@ -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());
} }
}; };
} }

View File

@@ -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";
}
}

View File

@@ -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) {