diff --git a/out/repos b/out/repos index 0ab4af2..d7baa10 160000 --- a/out/repos +++ b/out/repos @@ -1 +1 @@ -Subproject commit 0ab4af2faa92b28085e13cf2789ec1652cb7f0a9 +Subproject commit d7baa10c82b3cca734c172b3428850454f3c6c70 diff --git a/src/main/java/ru/molokoin/sourceListener/GitListener.java b/src/main/java/ru/molokoin/sourceListener/GitListener.java index 95c5ef9..c068bc9 100644 --- a/src/main/java/ru/molokoin/sourceListener/GitListener.java +++ b/src/main/java/ru/molokoin/sourceListener/GitListener.java @@ -4,42 +4,29 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.net.URI; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collection; import java.util.Enumeration; -import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.jgit.api.CheckoutCommand; -import org.eclipse.jgit.api.FetchCommand; import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.LsRemoteCommand; import org.eclipse.jgit.api.PullCommand; -import org.eclipse.jgit.api.Status; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.InvalidRemoteException; import org.eclipse.jgit.api.errors.TransportException; -import org.eclipse.jgit.diff.DiffEntry; -import org.eclipse.jgit.lib.Ref; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.revwalk.RevCommit; -import org.eclipse.jgit.transport.FetchResult; import com.fasterxml.jackson.core.exc.StreamReadException; import com.fasterxml.jackson.databind.DatabindException; import com.fasterxml.jackson.databind.ObjectMapper; -import ru.molokoin.sourceListener.git.RepoCrafter; -import ru.molokoin.sourceListener.net.Service; +import ru.molokoin.sourceListener.git.GitServiceFace; +import ru.molokoin.sourceListener.net.NetService; import ru.molokoin.sourceListener.opt.Options; public class GitListener { public Options opt; public String optionsPath = "options-home.json"; - private Repository repo; + public GitListener(){ try { opt = readOptions(); @@ -54,48 +41,14 @@ public class GitListener { e.printStackTrace(); } } + /** * Метод запускает бесконечный цикл проверки обновлений в репозитарии. */ public void live(){ //TODO live() } - /** - * Метод инициирует репозиторий / клонирует репозиторий - * по сути не нужный метод, реализующий одну команду. - * в коде надо использовать сразу клонирующую команду. - */ - public void initRepo(){ - try { - setRepo(RepoCrafter.copy(opt.getGitLink(), opt.getGitLocalPath())); - //repo.close(); - } catch (InvalidRemoteException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (TransportException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (GitAPIException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - /** - * Открываем репозитарий, ранее склонированный - * по хорошему делать статическим методом, возвращающим открытый репозитарий - * @throws IOException - */ - public void openRepo() throws IOException{ - Path repoPath = Paths.get("C:\\Users\\Strannik\\Documents\\esoe\\code\\sourceListener\\out\\repos"); - try (Git git = Git.open(repoPath.toFile())) { - this.repo = git.getRepository(); - git.close(); - } - - } + /** * Извлечение данных из options.json * @return @@ -109,9 +62,11 @@ public class GitListener { opt = mapper.readValue(new File(optionsPath), Options.class); return opt; } + public Options getOpt() { return opt; } + /** * распаковка архива */ @@ -135,57 +90,45 @@ public class GitListener { } } } - public void setRepo(Repository repo) { - this.repo = repo; - } - public Repository getRepo() { - return repo; - } - public static void main(String[] args) throws InvalidRemoteException, TransportException, GitAPIException { + + public static void main(String[] args) throws InvalidRemoteException, TransportException, GitAPIException, IOException { + //создаем объект класса, читаем файл с опциями GitListener ear = new GitListener(); - // try { - // Service.download(ear.opt.getZipLink(), ear.opt.getDownloadPath());; - // ear.extract(); - // } catch (IOException e) { - // System.out.println(e.getMessage()); - // } + Git git; - //клонируем репозитарий - // ear.initRepo(); - // Git git = new Git(ear.getRepo()); - - //открываем репозитарий из локального хранилища - try { - ear.openRepo(); - } catch (IOException e) { - System.out.println("Epic fail with >>>>> openRepo() ... "); - e.printStackTrace(); + /** + * инициализируем git: открываем существующий репозиратий или клонируем новый с удаленного репозитария + */ + Boolean isRepoExists = false; + if(isRepoExists){ + //открываем существующий репозиторий + git = GitServiceFace.open(ear.opt.getGitLocalPath()); + } else{ + //клонируем репозитарий + git = GitServiceFace.copy(ear.getOpt().getGitLink(), ear.getOpt().getGitLocalPath()); } - Git git = new Git(ear.getRepo()); - //получаем сведения об удаленных комитах - git.fetch().call(); - //System.out.println(">>>>>>>>>>>>>>>>>>>" + git.fetch().getRemote()); - Status status = git.status().call(); - System.out.println("Git Change: " + status.getChanged()); - System.out.println("Git Modified: " + status.getModified()); - System.out.println("Git UncommittedChanges: " + status.getUncommittedChanges()); - System.out.println("Git Untracked: " + status.getUntracked()); + Boolean isChanged = GitServiceFace.isChenged(git); + //если удаленная версия отличается от локальной, обновляем локальный репозитарий + if (isChanged){ + //забираем обновления с удаленного репозитария + System.out.println("забираем обновления с удаленного репозитария ..."); + CheckoutCommand checkout = git.checkout(); + checkout.setName("master"); + checkout.call(); + PullCommand pullCmd = git.pull(); + pullCmd.call(); + git.close(); + } - //выводим список комитов - try { - for (RevCommit c : git.log().all().call()) - System.out.println(c + ": " + c.getShortMessage()); - } catch (IOException e) { - System.out.println("git.log().all().call() >>>>>>> " + e.getMessage()); - e.printStackTrace(); + if (isChanged){ + //скачиваем и извлекаем архив репозитория + try { + NetService.download(ear.opt.getZipLink(), ear.opt.getDownloadPath()); + ear.extract(); + } catch (IOException e) { + System.out.println(e.getMessage()); + } } - //забираем обновления с удаленного репозитария - // CheckoutCommand checkout = git.checkout(); - // checkout.setName("master"); - // checkout.call(); - // PullCommand pullCmd = git.pull(); - // pullCmd.call(); - git.close(); } } diff --git a/src/main/java/ru/molokoin/sourceListener/git/GitServiceFace.java b/src/main/java/ru/molokoin/sourceListener/git/GitServiceFace.java new file mode 100644 index 0000000..6cbcfaf --- /dev/null +++ b/src/main/java/ru/molokoin/sourceListener/git/GitServiceFace.java @@ -0,0 +1,161 @@ +package ru.molokoin.sourceListener.git; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.eclipse.jgit.api.CheckoutCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PullCommand; +import org.eclipse.jgit.api.errors.CheckoutConflictException; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRefNameException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.NoHeadException; +import org.eclipse.jgit.api.errors.RefAlreadyExistsException; +import org.eclipse.jgit.api.errors.RefNotFoundException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.revwalk.RevCommit; + +/** + * Интерфейс взаимодействия с git + * предусматривает локальные и удаленные операции + * В качестве аргументов по большей части передается репозитарий, + * так же и возвращают методы обработанные репозитарии с уже проведенными изменениями + */ +public interface GitServiceFace { + + /** + * Метод предусматривает наличие в классе реализации механизма создания новых репозитариев + * !!! создавать новые репозитарии под текущие задачи не нужно + * @param localPath + * @return + */ + public static Repository create(String localPath){ + return null; + } + + /** + * Метод клонирует удаленный репозитарий, и размещает исходники на локальном устройстве + * @param gitLink + * @param localPath + * @return + * @throws GitAPIException + * @throws TransportException + * @throws InvalidRemoteException + * @throws IOException + */ + public static Git copy(String gitLink, String localPath) throws IOException, InvalidRemoteException, TransportException, GitAPIException{ + // подготовка локальных директорий для клонирования репозитария + File localFile = new File(localPath); + if(!localFile.delete()) { + throw new IOException("!!! файл уже существует: " + localPath + " ..."); + } + // непосредственно клонирование репозитария + System.out.println("Клонирование репозитария: " + gitLink); + System.out.println(); + Git result = Git.cloneRepository() + .setURI(gitLink) + .setDirectory(localFile) + .setCloneAllBranches(true) + .call(); + System.out.println("Копия репозитария создана в директории:\n>>>>>>> " + + result.getRepository().getDirectory()); + return result; + } + + /** + * Метод открывает размещенный по указанному пути репозитарий, + * возвращает его в готовом, для обработки виде. + * Далее: + * Git git = new Git(repo); + * и можно формировать команды для Гита + * @param localPath + * @return + * @throws IOException + */ + public static Git open(String localPath) throws IOException{ + Path repoPath = Paths.get(localPath); + Git git = Git.open(repoPath.toFile()); + return git; + } + + /** + * Закрывает полученную Git "команду"/командную строку + * @param git + */ + public static void close(Git git){ + git.close(); + } + + /** + * Метод сравнивает комиты в локальном репозитарии с данными удаленной ветки, + * в случае обнаружения разночтений возвращает true + * если список комитов остался прежним, возвращает false + * {Получили данные о локальных комитах -> подгрузили удаленные комиты -> прочитали данные удаленных комитов -> сравнили локальные с удаленными -> вернули ответ} + * !!! возможно стоит разбить на отдельные методы, но для текущей задачи это не нужно ... + * @throws GitAPIException + * @throws NoHeadException + * @throws IOException + */ + public static boolean isChenged(Git git) throws NoHeadException, GitAPIException, IOException{ + long old = 0; + long last = 0; + + /** + * Определяем время последнего комита в локальном репозитарии + */ + System.out.println("Определяем время последнего комита в локальном репозитарии ... "); + Iterable list = git.log().all().call(); + for (RevCommit c : list){ + long commitTime = c.getCommitTime(); + if (old < commitTime){ + old = commitTime; + } + } + System.out.println("Время последнего комита в локальном репозитарии: " + old); + + //получаем сведения об удаленных комитах + System.out.println("получаем сведения об удаленных комитах ..."); + System.out.println("Текущая ветка удаленного репозитария: " + git.fetch().getRemote()); + git.fetch().call(); + + //Определяем время последнего комита в удаленном репозитарии + System.out.println("Определяем время последнего комита в локальном репозитарии ... "); + list = git.log().all().call(); + for (RevCommit c : list){ + long commitTime = c.getCommitTime(); + if (last < commitTime){ + last = commitTime; + } + } + System.out.println("Время последнего комита в удаленном репозитарии: " + last); + //возвращает true, если время различается + return (old != last); + } + + /** + * Обновляет локальный репозитарий, синхронизирует с удаленным + * !!! в рамках текущей задачи: + * это наверно и не нужно, достаточно увидеть, что на удаленном репозитарии произошли изменения и отреагировать на них, загружать еще одну версию удаленного репозитария для этого не обязательно, достаточно только сведений о комитах. + * git pull + * @param git + * @return + * @throws GitAPIException + * @throws CheckoutConflictException + * @throws InvalidRefNameException + * @throws RefNotFoundException + * @throws RefAlreadyExistsException + */ + public static Git update(Git git) throws RefAlreadyExistsException, RefNotFoundException, InvalidRefNameException, CheckoutConflictException, GitAPIException{ + System.out.println("забираем обновления с удаленного репозитария ..."); + CheckoutCommand checkout = git.checkout(); + checkout.setName("master"); + checkout.call(); + PullCommand pullCmd = git.pull(); + pullCmd.call(); + return git; + } +} diff --git a/src/main/java/ru/molokoin/sourceListener/git/RepoCrafter.java b/src/main/java/ru/molokoin/sourceListener/git/RepoCrafter.java deleted file mode 100644 index eab691e..0000000 --- a/src/main/java/ru/molokoin/sourceListener/git/RepoCrafter.java +++ /dev/null @@ -1,55 +0,0 @@ -package ru.molokoin.sourceListener.git; - -import java.io.File; -import java.io.IOException; - -import org.eclipse.jgit.api.Git; -import org.eclipse.jgit.api.errors.GitAPIException; -import org.eclipse.jgit.api.errors.InvalidRemoteException; -import org.eclipse.jgit.api.errors.TransportException; -import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.storage.file.FileRepositoryBuilder; - -public class RepoCrafter { - - public static Repository open() throws IOException { - FileRepositoryBuilder builder = new FileRepositoryBuilder(); - return builder - .readEnvironment() // scan environment GIT_* variables - .findGitDir() // scan up the file system tree - .build(); - } - - public static Repository create() throws IOException { - // prepare a new folder - File localPath = File.createTempFile("TestGitRepository", ""); - if(!localPath.delete()) { - throw new IOException("Could not delete temporary file " + localPath); - } - - // create the directory - Repository repository = FileRepositoryBuilder.create(new File(localPath, ".git")); - repository.create(); - - return repository; - } - public static Repository copy(String gitLink, String localPath) throws IOException, InvalidRemoteException, TransportException, GitAPIException{ - // prepare a new folder for the cloned repository - File localFile = new File(localPath); - if(!localFile.delete()) { - throw new IOException("Could not delete temporary file " + localPath); - } - - // then clone - System.out.println("Cloning from " + gitLink + " to " + localPath); - Git result = Git.cloneRepository() - .setURI(gitLink) - .setDirectory(localFile) - .setCloneAllBranches(true) - //.setProgressMonitor(new SimpleProgressMonitor()) - .call(); - // Note: the call() returns an opened repository already which needs to be closed to avoid file handle leaks! - System.out.println("Having repository: " + result.getRepository().getDirectory()); - return result.getRepository(); - } -} \ No newline at end of file diff --git a/src/main/java/ru/molokoin/sourceListener/net/Service.java b/src/main/java/ru/molokoin/sourceListener/net/NetService.java similarity index 95% rename from src/main/java/ru/molokoin/sourceListener/net/Service.java rename to src/main/java/ru/molokoin/sourceListener/net/NetService.java index 1b1d5a5..10a18be 100644 --- a/src/main/java/ru/molokoin/sourceListener/net/Service.java +++ b/src/main/java/ru/molokoin/sourceListener/net/NetService.java @@ -7,7 +7,7 @@ import java.net.http.HttpResponse; import java.nio.file.Path; import java.nio.file.StandardOpenOption; -public class Service { +public class NetService { /** * Метод cкачивает файл c удаленного ресурса и размещает в указанной папке на локальном устройстве * @param sourceLink diff --git a/target/classes/ru/molokoin/sourceListener/GitListener.class b/target/classes/ru/molokoin/sourceListener/GitListener.class index 65d036f..19c9fee 100644 Binary files a/target/classes/ru/molokoin/sourceListener/GitListener.class and b/target/classes/ru/molokoin/sourceListener/GitListener.class differ diff --git a/target/classes/ru/molokoin/sourceListener/git/GitServiceFace.class b/target/classes/ru/molokoin/sourceListener/git/GitServiceFace.class new file mode 100644 index 0000000..ac154e6 Binary files /dev/null and b/target/classes/ru/molokoin/sourceListener/git/GitServiceFace.class differ diff --git a/target/classes/ru/molokoin/sourceListener/git/RepoCrafter.class b/target/classes/ru/molokoin/sourceListener/git/RepoCrafter.class deleted file mode 100644 index eef5fe0..0000000 Binary files a/target/classes/ru/molokoin/sourceListener/git/RepoCrafter.class and /dev/null differ diff --git a/target/classes/ru/molokoin/sourceListener/net/Service.class b/target/classes/ru/molokoin/sourceListener/net/NetService.class similarity index 82% rename from target/classes/ru/molokoin/sourceListener/net/Service.class rename to target/classes/ru/molokoin/sourceListener/net/NetService.class index bdcd286..14b8c6c 100644 Binary files a/target/classes/ru/molokoin/sourceListener/net/Service.class and b/target/classes/ru/molokoin/sourceListener/net/NetService.class differ