com.binarybirchtree.contributionart.Repository.java Source code

Java tutorial

Introduction

Here is the source code for com.binarybirchtree.contributionart.Repository.java

Source

// This file is part of ContributionArt.
// Copyright (C) 2015, 2016 Binary Birch Tree
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

package com.binarybirchtree.contributionart;

import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.DayOfWeek;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.time.temporal.WeekFields;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Logger;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.PersonIdent;

public class Repository implements AutoCloseable {
    private static final Logger LOGGER = Logger.getLogger(Repository.class.getName());

    public class GitException extends Exception {
        GitException(String message) {
            super(message);
        }
    }

    private Path directory;
    private Git git;
    private String name;
    private String email;

    @Override
    public void close() {
        git.close();
    }

    ///
    /// @param[in] directory Directory of the repository.
    /// @param[in] name User name.
    /// @param[in] email Email address.
    ///
    public Repository(Path directory, String name, String email) throws IOException, GitException {
        this.directory = directory;
        this.name = name;
        this.email = email;

        try {
            Git.init().setDirectory(directory.toFile()).setBare(false).call();
            git = Git.open(directory.toFile());
            LOGGER.info(String.format("Initialized Git repository at '%s'.", directory));
        } catch (GitAPIException error) {
            throw new GitException(error.toString());
        }
    }

    ///
    /// Adds commits to the repository so as to form an illustrated version of the specified matrix
    /// when viewed as a GitHub contribution graph.
    ///
    /// @param[in] matrix Matrix to illustrate.
    /// @param[in] factor Scaling factor.
    /// @param[in] timestamp Timestamp containing the current date to use to render the matrix.
    ///
    public void illustrate(Matrix matrix, int factor, ZonedDateTime timestamp) throws GitException, IOException {
        ZonedDateTime now = ZonedDateTime.now();

        // Start from the earliest date, which corresponds to the first value in the definition matrix.
        ZonedDateTime current = timestamp.truncatedTo(ChronoUnit.DAYS)
                .with(WeekFields.SUNDAY_START.dayOfWeek(), DayOfWeek.values().length).minusDays(Matrix.AREA);

        for (Matrix.Value value : matrix) {
            current = current.plusDays(1);

            // Skip values that correspond to dates later than the specified timestamp.
            if (current.isBefore(now) || current.isEqual(now)) {
                // The number of commits to generate for a particular date depends on
                // the corresponding value in the definition matrix and the scaling factor.
                int weight = value.weight() * factor;

                try {
                    PersonIdent identity = identity(current);
                    for (int i = 0; i < weight; ++i) {
                        git.commit().setMessage("").setAuthor(identity).setCommitter(identity).call();
                    }
                } catch (GitAPIException error) {
                    throw new GitException(error.toString());
                }

                LOGGER.info(String.format("Created %d commit%s with timestamp %s.", weight, weight > 1 ? "s" : "",
                        current));
            }
        }

        create_file(directory.resolve("README.md"), README, timestamp.truncatedTo(ChronoUnit.DAYS));
    }

    public void illustrate(Matrix matrix, int factor) throws GitException, IOException {
        illustrate(matrix, factor, ZonedDateTime.now(ZoneOffset.UTC));
    }

    ///
    /// Creates a file at the specified path with the specified contents and commit timestamp.
    ///
    /// @param[in] file File path.
    /// @param[in] contents File contents.
    /// @param[in] timestamp Commit timestamp.
    ///
    protected void create_file(Path file, String contents, ZonedDateTime timestamp)
            throws GitException, IOException {
        try (BufferedWriter writer = Files.newBufferedWriter(file)) {
            writer.write(contents);
        }

        try {
            git.add().addFilepattern(directory.relativize(file).toString()).call();
            PersonIdent identity = identity(timestamp);
            git.commit().setMessage(String.format("Added %s.", file.getFileName().toString())).setAuthor(identity)
                    .setCommitter(identity).call();
        } catch (GitAPIException error) {
            throw new GitException(error.toString());
        }

        LOGGER.info(
                String.format("Created file '%s' with timestamp %s and contents '%s'.", file, timestamp, contents));
    }

    ///
    /// @param[in] timestamp Timestamp.
    /// @return PersonIdent for the specified timestamp.
    ///
    private PersonIdent identity(ZonedDateTime timestamp) {
        return new PersonIdent(name, email, Date.from(timestamp.toInstant()),
                TimeZone.getTimeZone(timestamp.getZone()));
    }

    public static String README = "# Contribution Graph Artwork\n\n"
            + "This repository was programmatically generated by [ContributionArt](https://github.com/binarybirchtree/contributionart/), "
            + "a tool which allows custom-designed artwork to be displayed on the GitHub contribution graph.\n";
}