Java tutorial
/** * Copyright 2005-2014 Red Hat, Inc. * * Red Hat 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 io.fabric8.maven; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; import io.fabric8.utils.Files; import io.fabric8.utils.Strings; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.InitCommand; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.lib.StoredConfig; import org.eclipse.jgit.storage.file.FileRepositoryBuilder; import org.eclipse.jgit.transport.CredentialsProvider; import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; import org.gitective.core.RepositoryUtils; import static io.fabric8.git.internal.GitHelpers.checkoutBranch; import static io.fabric8.git.internal.GitHelpers.createOrCheckoutBranch; /** * Generates a git branch in the given git repository using the given profile zips as the profile data */ @Mojo(name = "branch", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME) @Execute(phase = LifecyclePhase.PACKAGE) public class CreateBranchMojo extends AbstractProfileMojo { /** * Name of the directory used to clone the git repository */ @Parameter(property = "fabric8.branch.buildDir", defaultValue = "${project.build.directory}/git") private File buildDir; /** * Name of the branch to create */ @Parameter(property = "fabric8.branch.branchName", required = true) private String branchName; /** * Name of the old branch to base the new branch off. If not specified then it defaults to the last branch created. */ @Parameter(property = "fabric8.branch.oldBranchName") private String oldBranchName; /** * The URL of the remote git repository to clone. If blank it will just create a local git repository */ @Parameter(property = "fabric8.branch.gitUrl") private String gitUrl; /** * Name of the directory used to create the full profiles configuration zip */ @Parameter(property = "fabric8.branch.cloneAllBranches", defaultValue = "true") private boolean cloneAll; /** * Should we perform a git pull before creating the new branch */ @Parameter(property = "fabric8.branch.pullOnStartup", defaultValue = "true") private boolean pullOnStartup; /** * Name of the remote git repository */ @Parameter(property = "fabric8.branch.remoteName", defaultValue = "origin") private String remoteName = "origin"; private Git git; @Override public void execute() throws MojoExecutionException, MojoFailureException { try { initGitRepo(); createAndCheckoutBranch(); addProfileZips(); removeSelectedFiles(); commit("Branch created by fabric8 maven plugin"); } catch (MojoExecutionException e) { throw e; } catch (Exception e) { throw new MojoExecutionException("Error executing", e); } } /** * unzips any dependent zips into the git directory */ protected void addProfileZips() throws MojoExecutionException, IOException, GitAPIException { Set<Artifact> dependencyArtifacts = project.getDependencyArtifacts(); for (Artifact artifact : dependencyArtifacts) { if ("zip".equals(artifact.getType())) { File file = artifact.getFile(); if (file != null) { getLog().info("Unzipping file: " + file); addZipFile(file); } else { getLog().warn("Could not resolve file for " + artifact); } } } git.add().addFilepattern("fabric").call(); } protected void addZipFile(File file) throws MojoExecutionException, IOException, GitAPIException { if (file == null || !file.exists() || !file.isFile()) { throw new MojoExecutionException("Zip file does not exist: " + file); } File unzipDir = new File(buildDir, "fabric/profiles"); unzipDir.mkdirs(); try { Zips.unzip(new FileInputStream(file), unzipDir); } catch (IOException e) { throw new MojoExecutionException("Failed to unzip file " + file.getCanonicalPath() + " to " + getGitBuildPathDescription() + ". " + e, e); } } /** * Removes any unrequired files from the branch before its committed */ protected void removeSelectedFiles() throws MojoExecutionException, IOException, GitAPIException { } protected void initGitRepo() throws MojoExecutionException, IOException, GitAPIException { buildDir.mkdirs(); File gitDir = new File(buildDir, ".git"); if (!gitDir.exists()) { String repo = gitUrl; if (Strings.isNotBlank(repo)) { getLog().info("Cloning git repo " + repo + " into directory " + getGitBuildPathDescription() + " cloneAllBranches: " + cloneAll); CloneCommand command = Git.cloneRepository().setCloneAllBranches(cloneAll).setURI(repo) .setDirectory(buildDir).setRemote(remoteName); // .setCredentialsProvider(getCredentials()). try { git = command.call(); return; } catch (Throwable e) { getLog().error("Failed to command remote repo " + repo + " due: " + e.getMessage(), e); // lets just use an empty repo instead } } else { InitCommand initCommand = Git.init(); initCommand.setDirectory(buildDir); git = initCommand.call(); getLog().info("Initialised an empty git configuration repo at " + getGitBuildPathDescription()); // lets add a dummy file File readMe = new File(buildDir, "ReadMe.md"); getLog().info("Generating " + readMe); Files.writeToFile(readMe, "fabric8 git repository created by fabric8-maven-plugin at " + new Date(), Charset.forName("UTF-8")); git.add().addFilepattern("ReadMe.md").call(); commit("Initial commit"); } String branch = git.getRepository().getBranch(); configureBranch(branch); } else { getLog().info("Reusing existing git repository at " + getGitBuildPathDescription()); FileRepositoryBuilder builder = new FileRepositoryBuilder(); Repository repository = builder.setGitDir(gitDir).readEnvironment() // scan environment GIT_* variables .findGitDir() // scan up the file system tree .build(); git = new Git(repository); if (pullOnStartup) { doPull(); } else { getLog().info("git pull from remote config repo on startup is disabled"); } } } protected void configureBranch(String branch) { // lets update the merge config if (Strings.isNotBlank(branch) && hasRemoteRepo()) { StoredConfig config = git.getRepository().getConfig(); if (Strings.isNullOrBlank(config.getString("branch", branch, "remote")) || Strings.isNullOrBlank(config.getString("branch", branch, "merge"))) { config.setString("branch", branch, "remote", remoteName); config.setString("branch", branch, "merge", "refs/heads/" + branch); try { config.save(); } catch (IOException e) { getLog().error("Failed to save the git configuration into " + new File(buildDir, ".git") + " with branch " + branch + " on remote repo: " + gitUrl + " due: " + e.getMessage() + ". This exception is ignored.", e); } } } } /** * Returns true if the remote git url is defined or the local git repo has a remote url defined */ protected boolean hasRemoteRepo() { if (Strings.isNotBlank(gitUrl)) { return true; } Repository repository = git.getRepository(); StoredConfig config = repository.getConfig(); String url = config.getString("remote", remoteName, "url"); if (Strings.isNotBlank(url)) { return true; } return false; } protected void doPull() throws MojoExecutionException { //CredentialsProvider cp = getCredentials(); CredentialsProvider cp = null; try { Repository repository = git.getRepository(); StoredConfig config = repository.getConfig(); String url = config.getString("remote", "origin", "url"); if (Strings.isNullOrBlank(url)) { getLog().info("No remote repository defined for the git repository at " + getGitBuildPathDescription() + " so not doing a pull"); return; } String branch = repository.getBranch(); String mergeUrl = config.getString("branch", branch, "merge"); if (Strings.isNullOrBlank(mergeUrl)) { getLog().info("No merge spec for branch." + branch + ".merge in the git repository at " + getGitBuildPathDescription() + " so not doing a pull"); return; } getLog().info("Performing a pull in git repository " + getGitBuildPathDescription() + " on remote URL: " + url); git.pull().setCredentialsProvider(cp).setRebase(true).call(); } catch (Throwable e) { String credText = ""; if (cp instanceof UsernamePasswordCredentialsProvider) { } String message = "Failed to pull from the remote git repo with credentials " + cp + " due: " + e.getMessage() + ". This exception is ignored."; getLog().error(message, e); throw new MojoExecutionException(message, e); } } protected void createAndCheckoutBranch() throws MojoExecutionException, IOException, GitAPIException { if (Strings.isNullOrBlank(oldBranchName)) { // lets find the previous branch List<String> branches = new ArrayList<String>(RepositoryUtils.getBranches(git.getRepository())); int size = branches.size(); if (size > 0) { String last = branches.get(size - 1); int idx = last.lastIndexOf('/'); if (idx > 0) { oldBranchName = last.substring(idx + 1); getLog().info("Using previous branch: " + oldBranchName); } } } if (Strings.isNullOrBlank(oldBranchName)) { oldBranchName = "master"; getLog().warn("Could not deduce the old branch so setting it to: " + oldBranchName); } checkoutBranch(git, oldBranchName); getLog().info("Creating branch " + branchName + " in " + getGitBuildPathDescription()); createOrCheckoutBranch(git, branchName, remoteName); checkoutBranch(git, branchName); } protected void commit(String message) throws GitAPIException { git.commit().setMessage(message).call(); } protected String getGitBuildPathDescription() throws IOException { return buildDir.getCanonicalPath(); } }