net.morimekta.idltool.IdlUtils.java Source code

Java tutorial

Introduction

Here is the source code for net.morimekta.idltool.IdlUtils.java

Source

/*
 * Copyright (c) 2016, Stein Eldar Johnsen
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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;

import com.google.common.collect.ImmutableSortedMap;
import net.morimekta.idltool.config.IdlRC;
import net.morimekta.idltool.config.Idl_Constants;
import net.morimekta.idltool.meta.Meta;
import net.morimekta.providence.serializer.JsonSerializer;
import net.morimekta.util.io.IOUtils;
import org.apache.commons.codec.digest.DigestUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
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.TreeWalk;
import org.eclipse.jgit.treewalk.filter.PathFilter;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Clock;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Base64;
import java.util.Map;
import java.util.Properties;

/**
 * General IDL tool utilities.
 */
public class IdlUtils {
    public static String versionString() {
        Properties properties = new Properties();
        try (InputStream in = IdlUtils.class.getResourceAsStream("/build.properties")) {
            properties.load(in);
            return "v" + properties.getProperty("build.version");
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private static File getCacheDirectory(File cacheDir, String repository) throws IOException {
        if (!cacheDir.exists()) {
            if (!cacheDir.mkdirs()) {
                throw new IOException(
                        "Unable to create cache directory " + cacheDir.getCanonicalFile().getAbsolutePath());
            }
        }

        String hash = Base64.getUrlEncoder()
                .encodeToString(DigestUtils.sha1(repository.getBytes(StandardCharsets.UTF_8)));
        return new File(cacheDir, hash).getCanonicalFile().getAbsoluteFile();
    }

    public static Git getCacheRepository(File cacheDir, String repository) throws IOException, GitAPIException {
        File repoCache = getCacheDirectory(cacheDir, repository);

        Runtime runtime = Runtime.getRuntime();
        if (!repoCache.exists()) {
            Process p = runtime
                    .exec(new String[] { "git", "clone", repository, repoCache.getAbsoluteFile().toString() });
            try {
                int response = p.waitFor();
                if (response != 0) {
                    throw new IOException(IOUtils.readString(p.getErrorStream()));
                }
            } catch (InterruptedException e) {
                throw new IOException(e.getMessage(), e);
            }
        } else {
            Process p = runtime.exec(new String[] { "git", "fetch", "origin", "-p" }, null, repoCache);
            try {
                int response = p.waitFor();
                if (response != 0) {
                    throw new IOException(IOUtils.readString(p.getErrorStream()));
                }
            } catch (InterruptedException e) {
                throw new IOException(e.getMessage(), e);
            }

            p = runtime.exec(new String[] { "git", "add", "-A" }, null, repoCache);
            try {
                int response = p.waitFor();
                if (response != 0) {
                    throw new IOException(IOUtils.readString(p.getErrorStream()));
                }
            } catch (InterruptedException e) {
                throw new IOException(e.getMessage(), e);
            }

            p = runtime.exec(new String[] { "git", "reset", "origin/master", "--hard" }, null, repoCache);
            try {
                int response = p.waitFor();
                if (response != 0) {
                    throw new IOException(IOUtils.readString(p.getErrorStream()));
                }
            } catch (InterruptedException e) {
                throw new IOException(e.getMessage(), e);
            }
        }
        return Git.open(repoCache);
    }

    public static IdlRC readRepoRc(File rc) throws IOException {
        try (FileInputStream in = new FileInputStream(rc)) {
            return new JsonSerializer().deserialize(in, IdlRC.kDescriptor);
        }
    }

    public static File findHomeDotCacheIdlTool(File cacheOverride) throws IOException {
        if (cacheOverride != null) {
            cacheOverride = cacheOverride.getCanonicalFile();
            if (cacheOverride.exists() && cacheOverride.isDirectory()) {
                return cacheOverride;
            }
            throw new IOException("No such cache directory: " + cacheOverride.toString());
        }

        File home = new File(System.getenv("HOME")).getAbsoluteFile().getCanonicalFile();
        cacheOverride = new File(new File(home, ".cache"), "idltool");
        if (!cacheOverride.exists()) {
            if (!cacheOverride.mkdirs()) {
                throw new IOException("Unable to create RC directory: " + cacheOverride.toString());
            }
        }
        if (!cacheOverride.isDirectory()) {
            throw new IOException("RC location is not a directory: " + cacheOverride.toString());
        }
        return cacheOverride;
    }

    public static File findRepoRc(File workingDir, boolean recursive) throws IOException {
        if (workingDir == null) {
            throw new IllegalArgumentException("No working directory");
        }
        if (!workingDir.exists()) {
            throw new IOException("No such directory: " + workingDir.toString());
        }
        if (!workingDir.isDirectory()) {
            throw new IOException("No RC location not a directory: " + workingDir.toString());
        }

        File pwd = workingDir;
        File rc = new File(pwd, ".idlrc");
        if (recursive) {
            while (!rc.exists()) {
                pwd = pwd.getParentFile();
                if (pwd == null) {
                    throw new IOException("No .idlrc file at: " + workingDir.getAbsolutePath() + " (recursive)");
                }
                rc = new File(pwd, ".idlrc");
            }
        }
        if (!rc.exists()) {
            throw new IOException("No .idlrc file at: " + workingDir.getAbsolutePath());
        }
        if (!rc.isFile()) {
            throw new IOException("Found .idlrc is not a file: " + pwd.getAbsolutePath());
        }
        return rc;
    }

    public static String getLocalRemoteName(Repository repository, String remoteName) throws IOException {
        Config config = repository.getConfig();
        String currentBranch = repository.getBranch();
        if (currentBranch == null) {
            throw new RuntimeException("No current branch!");
        }

        if (remoteName == null) {
            String branch = config.getString("default", null, "branch");
            if (branch == null) {
                branch = "master";
            }

            remoteName = config.getString("branch", branch, "remote");
            if (remoteName == null) {
                remoteName = config.getString("branch", "master", "remote");
                if (remoteName == null) {
                    remoteName = "origin";
                }
            }
        }
        String remoteUrl = config.getString("remote", remoteName, "url");
        if (remoteUrl == null) {
            throw new RuntimeException("No URL for remote " + remoteName);
        }

        return remoteUrl.replaceAll("^.*://", "").replaceAll("^.*@", "").replaceAll("[.]git$", "").replaceAll(":",
                "/");
    }

    public static Meta getMetaInRegistry(Repository repo) throws IOException, GitAPIException {
        // use tree and meta.json file to show available services.
        ObjectId lastCommitId = repo.resolve(Constants.HEAD);
        // now we have to get the commit
        RevWalk revWalk = new RevWalk(repo);
        RevCommit commit = revWalk.parseCommit(lastCommitId);
        // and using commit's tree find the path
        RevTree tree = commit.getTree();
        TreeWalk treeWalk = new TreeWalk(repo);

        treeWalk.addTree(tree);
        treeWalk.setRecursive(true);
        treeWalk.setFilter(PathFilter.create(Idl_Constants.META_JSON));
        if (!treeWalk.next()) {
            throw new RuntimeException("No registry meta file found, should be at "
                    + new File(repo.getDirectory(), Idl_Constants.META_JSON).getCanonicalFile().getAbsolutePath());
        }
        ObjectId objectId = treeWalk.getObjectId(0);
        ObjectLoader loader = repo.open(objectId);

        // and then one can use either
        InputStream in = loader.openStream();

        return new JsonSerializer().deserialize(in, Meta.kDescriptor);
    }

    public static String formatAgo(long timestamp) {
        Instant instant = Instant.ofEpochSecond(timestamp / 1000);
        LocalDateTime local = instant.atZone(Clock.systemUTC().getZone())
                .withZoneSameInstant(Clock.systemDefaultZone().getZone()).toLocalDateTime();
        return DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(local).replaceAll("[T]", " ");
    }

    public static Map<String, String> buildSha1Sums(Path dir) throws IOException {
        ImmutableSortedMap.Builder<String, String> sha1sums = ImmutableSortedMap.naturalOrder();

        // TODO: Support nested directories.
        Files.list(dir).forEach(file -> {
            try {
                if (Files.isRegularFile(file)) {
                    String sha = DigestUtils.sha1Hex(Files.readAllBytes(file));
                    sha1sums.put(file.getFileName().toString(), sha);
                }
            } catch (IOException e) {
                throw new UncheckedIOException(e.getMessage(), e);
            }
        });

        return sha1sums.build();
    }
}