/** * Copyright [2015] [Christian Loehnert] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.ks.blogging.grav.pages; import com.google.common.base.Charsets; import de.ks.blogging.grav.entity.GravBlog; import org.apache.commons.net.ftp.FTPSClient; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.diff.DiffEntry; import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectReader; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevTree; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.treewalk.AbstractTreeIterator; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.function.Consumer; public class RepositorySupport { private static final Logger log = LoggerFactory.getLogger(RepositorySupport.class); private final GravPages pages; public RepositorySupport(GravPages pages) { this.pages = pages; } public String getLastGitRev() { GravBlog blog = pages.getBlog(); try (RemoteFtpClient c = new RemoteFtpClient(blog)) { FTPSClient ftpsClient = c.getFtpsClient(); try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) { ftpsClient.retrieveFile("git-rev.txt", byteArrayOutputStream); String revision = byteArrayOutputStream.toString(Charsets.US_ASCII.name()); return revision.trim(); } } catch (Exception e) { log.error("Could not retrieve git revision ", e); return null; } } public FileChanges getChangedFiles(String from) { return getChangedFiles(from, "master"); } public FileChanges getChangedFiles(String from, String to) { try { Git git = pages.getGit(); Repository repository = git.getRepository(); List<DiffEntry> diffs = git.diff().setNewTree(prepareTreeParser(repository, to)).setOldTree(prepareTreeParser(repository, from)).call(); FileChanges fileChanges = new FileChanges(diffs); log.info("Found {} added/modified, {} deleted.", fileChanges.getModifiedAdded().size(), fileChanges.getDeleted().size()); return fileChanges; } catch (Exception e) { log.error("Could not get changed files ", e); } return new FileChanges(Collections.emptyList()); } public void upload(FileChanges fileChanges, Consumer<Integer> processCallback) { GravBlog blog = pages.getBlog(); try (RemoteFtpClient c = new RemoteFtpClient(blog)) { FTPSClient ftpsClient = c.getFtpsClient(); for (String path : fileChanges.getDeleted()) { log.info("Deleting remote file {}", path); try { File root = pages.getGit().getRepository().getDirectory().getParentFile(); File file = new File(root, path); changeToMkdir(ftpsClient, root, file); ftpsClient.deleteFile(path); processCallback.accept(1); c.resetToWorkingDir(); } catch (IOException e) { log.error("Could not delete {}", path, e); } } for (String path : fileChanges.getModifiedAdded()) { try { File root = pages.getGit().getRepository().getDirectory().getParentFile(); File file = new File(root, path); changeToMkdir(ftpsClient, root, file); try (FileInputStream stream = new FileInputStream(new File(root, path))) { log.info("Uploading file {}", path); ftpsClient.storeFile(file.getName(), stream); processCallback.accept(1); } c.resetToWorkingDir(); } catch (IOException e) { log.error("Could not create/update {}", path, e); } } } catch (Exception e) { log.error("Could not upload file changes ", e); } } protected void changeToMkdir(FTPSClient ftpsClient, File root, File file) throws IOException { ArrayList<File> parents = new ArrayList<>(); for (File parent = file.getParentFile(); !parent.equals(root); parent = parent.getParentFile()) { parents.add(parent); } Collections.reverse(parents); for (File parent : parents) { boolean couldChange = ftpsClient.changeWorkingDirectory(parent.getName()); if (!couldChange) { ftpsClient.mkd(parent.getName()); ftpsClient.changeWorkingDirectory(parent.getName()); } } } private static AbstractTreeIterator prepareTreeParser(Repository repository, String objectId) throws IOException, IncorrectObjectTypeException { RevWalk walk = new RevWalk(repository); ObjectId resolve = repository.resolve(objectId); RevCommit commit = walk.parseCommit(resolve); RevTree tree = walk.parseTree(commit.getTree().getId()); CanonicalTreeParser oldTreeParser = new CanonicalTreeParser(); try (ObjectReader oldReader = repository.newObjectReader()) { oldTreeParser.reset(oldReader, tree.getId()); } walk.dispose(); return oldTreeParser; } }