de.ks.blogging.grav.pages.RepositorySupport.java Source code

Java tutorial

Introduction

Here is the source code for de.ks.blogging.grav.pages.RepositorySupport.java

Source

/**
 * 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;
    }
}