net.morimekta.idltool.cmd.RemotePublish.java Source code

Java tutorial

Introduction

Here is the source code for net.morimekta.idltool.cmd.RemotePublish.java

Source

/*
 * Copyright 2017 (c) Stein Eldar Johnsen
 *
 * 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 net.morimekta.idltool.cmd;

import com.google.common.collect.ImmutableMap;
import net.morimekta.console.args.ArgumentParser;
import net.morimekta.idltool.IdlTool;
import net.morimekta.idltool.IdlUtils;
import net.morimekta.idltool.config.Idl_Constants;
import net.morimekta.idltool.meta.Meta;
import net.morimekta.idltool.meta.Remote;
import net.morimekta.providence.serializer.JsonSerializer;
import net.morimekta.util.io.IOUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Clock;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;

/**
 * Interactively manage branches.
 */
public class RemotePublish extends Command {
    public RemotePublish(ArgumentParser parent) {
        super(parent);
    }

    @Override
    public ArgumentParser makeParser() {
        ArgumentParser parser = new ArgumentParser(getParent(), "publish",
                "Update published IDL for the current repository to latest version.");

        return parser;
    }

    @Override
    public void execute(IdlTool idlTool) throws IOException, GitAPIException {
        String repository = idlTool.getIdl().getUpstreamRepository();
        File pwd = idlTool.getIdl().getWorkingGitDir();

        Git cacheRepository = idlTool.getRepositoryGitCache(repository);

        Path localIDL = pwd.toPath().resolve(Idl_Constants.IDL);
        Path localPath = localIDL.resolve(idlTool.getLocalRemoteName());

        if (!Files.exists(localPath)) {
            Path relative = pwd.toPath().relativize(localPath);
            System.out.println("No IDL dir in local remote location: .../" + relative);
            return;
        }

        Map<String, String> localSha1sums = IdlUtils.buildSha1Sums(localPath);
        if (localSha1sums.isEmpty()) {
            Path relative = pwd.toPath().relativize(localPath);
            System.out.println("No IDL files in local remote location: .../" + relative);
            return;
        }

        Meta cacheMeta = IdlUtils.getMetaInRegistry(cacheRepository.getRepository());
        Remote cacheRemote = cacheMeta.hasRemotes()
                && cacheMeta.getRemotes().containsKey(idlTool.getLocalRemoteName())
                        ? cacheMeta.getRemotes().get(idlTool.getLocalRemoteName())
                        : Remote.builder().build();

        Map<String, String> publishedSha1sums = ImmutableMap.of();
        if (cacheRemote.hasShasums()) {
            publishedSha1sums = cacheMeta.getRemotes().get(idlTool.getLocalRemoteName()).getShasums();
        }

        if (localSha1sums.equals(publishedSha1sums)) {
            // No change.
            System.out.println("No change.");
            return;
        }

        Path remoteIDL = cacheRepository.getRepository().getWorkTree().toPath().resolve(Idl_Constants.IDL);
        Path remotePath = remoteIDL.resolve(idlTool.getLocalRemoteName());
        if (Files.isDirectory(remotePath)) {
            Files.list(remotePath).forEach(file -> {
                try {
                    String name = file.getFileName().toString();
                    if (Files.isHidden(file) || !Files.isRegularFile(file)) {
                        // Hidden and special files are ignored.
                        return;
                    }
                    if (!localSha1sums.containsKey(name)) {
                        Files.delete(file);
                    }
                } catch (IOException e) {
                    throw new UncheckedIOException(e.getMessage(), e);
                }
            });
        } else {
            Files.createDirectories(remotePath);
        }

        for (String file : localSha1sums.keySet()) {
            Path source = localPath.resolve(file);
            Path target = remotePath.resolve(file);

            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
        }

        ZonedDateTime now = ZonedDateTime.now(Clock.systemUTC());
        long timestamp = now.toInstant().toEpochMilli();
        String isoNow = DateTimeFormatter.ISO_DATE_TIME.format(now);

        Remote._Builder remoteBuilder = Remote.builder();
        remoteBuilder.setVersion(timestamp);
        remoteBuilder.setTime(timestamp);
        remoteBuilder.setShasums(localSha1sums);

        Meta._Builder metaBuilder = cacheMeta.mutate();
        metaBuilder.putInRemotes(idlTool.getLocalRemoteName(), remoteBuilder.build());
        metaBuilder.setVersion(timestamp);
        metaBuilder.setTime(isoNow);

        try (FileOutputStream out = new FileOutputStream(
                new File(cacheRepository.getRepository().getWorkTree(), Idl_Constants.META_JSON))) {
            new JsonSerializer().pretty().serialize(out, metaBuilder.build());
            out.write('\n');
        }

        Process add = Runtime.getRuntime().exec(new String[] { "git", "add", "." }, null,
                cacheRepository.getRepository().getWorkTree());
        try {
            int response = add.waitFor();
            if (response != 0) {
                throw new IOException(IOUtils.readString(add.getErrorStream()));
            }
        } catch (InterruptedException e) {
            throw new IOException(e.getMessage(), e);
        }

        cacheRepository.commit().setMessage("Updating " + idlTool.getLocalRemoteName() + " to latest version")
                .call();
        cacheRepository.tag().setName("v" + timestamp).setMessage(isoNow + " " + idlTool.getLocalRemoteName())
                .call();

        Process commit = Runtime.getRuntime().exec(new String[] { "git", "push" }, null,
                cacheRepository.getRepository().getWorkTree());
        try {
            int response = commit.waitFor();
            if (response != 0) {
                throw new IOException(IOUtils.readString(commit.getErrorStream()));
            }
        } catch (InterruptedException e) {
            throw new IOException(e.getMessage(), e);
        }

        commit = Runtime.getRuntime().exec(new String[] { "git", "push", "--tags" }, null,
                cacheRepository.getRepository().getWorkTree());
        try {
            int response = commit.waitFor();
            if (response != 0) {
                throw new IOException(IOUtils.readString(commit.getErrorStream()));
            }
        } catch (InterruptedException e) {
            throw new IOException(e.getMessage(), e);
        }
    }
}