diff --git a/README.md b/README.md index bd9063e..afec2b7 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,9 @@ git clone --mirror git@github.com:bozaro/git-lfs-migrate.git # -c, --cache # Source repository # Default: . +# --check-lfs +# Check LFS server settings and exit +# Default: false # * -d, --destination # Destination repository # -g, --git diff --git a/build.gradle b/build.gradle index 244c24f..4e91ac2 100644 --- a/build.gradle +++ b/build.gradle @@ -23,8 +23,8 @@ dependencies { compile "org.jgrapht:jgrapht-core:0.9.1" compile "com.beust:jcommander:1.35" - compile "ru.bozaro.gitlfs:gitlfs-pointer:0.6.0" - compile "ru.bozaro.gitlfs:gitlfs-client:0.6.0" + compile "ru.bozaro.gitlfs:gitlfs-pointer:0.7.0" + compile "ru.bozaro.gitlfs:gitlfs-client:0.7.0" testCompile "org.testng:testng:6.8.8" } diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..3e09583 --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = "git-lfs-migrate" diff --git a/src/main/java/git/lfs/migrate/Main.java b/src/main/java/git/lfs/migrate/Main.java index 00e042a..8a4a627 100644 --- a/src/main/java/git/lfs/migrate/Main.java +++ b/src/main/java/git/lfs/migrate/Main.java @@ -2,6 +2,7 @@ import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; +import org.apache.commons.httpclient.HttpStatus; import org.eclipse.jgit.lib.*; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.jetbrains.annotations.NotNull; @@ -15,7 +16,9 @@ import ru.bozaro.gitlfs.client.Client; import ru.bozaro.gitlfs.client.auth.AuthProvider; import ru.bozaro.gitlfs.client.auth.BasicAuthProvider; -import ru.bozaro.gitlfs.common.data.Meta; +import ru.bozaro.gitlfs.client.exceptions.ForbiddenException; +import ru.bozaro.gitlfs.common.data.*; +import ru.bozaro.gitlfs.common.data.Error; import java.io.File; import java.io.IOException; @@ -57,10 +60,58 @@ public static void main(@NotNull String[] args) throws IOException, InterruptedE } else { auth = null; } + if (!checkLfsAuthenticate(auth)) { + return; + } + if (cmd.checkLfs) { + if (auth == null) { + log.error("Git LFS server is not defined."); + } + return; + } processRepository(cmd.src, cmd.dst, cmd.cache, auth, cmd.writeThreads, cmd.uploadThreads, cmd.suffixes.toArray(new String[cmd.suffixes.size()])); log.info("Convert time: {}", System.currentTimeMillis() - time); } + private static boolean checkLfsAuthenticate(@Nullable AuthProvider auth) throws IOException { + if (auth == null) + return true; + final Meta meta = new Meta("0123456789012345678901234567890123456789012345678901234567890123", 42); + Client client = new Client(auth); + try { + BatchRes response = client.postBatch( + new BatchReq(Operation.Upload, Collections.singletonList( + meta + )) + ); + if (response.getObjects().size() != 1) { + log.error("LFS server: Invalid response for test batch request"); + } + Error error = response.getObjects().get(0).getError(); + if (error != null) { + if (error.getCode() == HttpStatus.SC_FORBIDDEN) { + log.error("LFS server: Upload access denied"); + } else { + log.error("LFS server: Upload denied with error: " + error.getMessage()); + } + } + log.info("LFS server: OK"); + return true; + } catch (ForbiddenException e) { + log.error("LFS server: Access denied", e); + return false; + } catch (IOException e) { + log.info("LFS server: Batch API request exception", e); + } + try { + client.getMeta(meta.getOid()); + log.error("LFS server: Unsupported batch API"); + } catch (IOException ignored) { + log.error("LFS server: Invalid base URL"); + } + return false; + } + public static void processRepository(@NotNull File srcPath, @NotNull File dstPath, @NotNull File cachePath, @Nullable AuthProvider auth, int writeThreads, int uploadThreads, @NotNull String... suffixes) throws IOException, InterruptedException, ExecutionException { removeDirectory(dstPath); dstPath.mkdirs(); @@ -366,11 +417,12 @@ public static class CmdArgs { private int writeThreads = 2; @Parameter(names = {"-u", "--upload-threads"}, description = "HTTP upload thread count", required = false) private int uploadThreads = 4; + @Parameter(names = {"--check-lfs"}, description = "Check LFS server settings and exit") + private boolean checkLfs = false; @Parameter(description = "LFS file suffixes") @NotNull private List suffixes = new ArrayList<>(); - @Parameter(names = {"-h", "--help"}, description = "Show help", help = true) private boolean help = false; }