001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.scm.provider.git.jgit.command.info; 020 021import java.io.File; 022import java.io.IOException; 023import java.util.LinkedList; 024import java.util.List; 025 026import org.apache.commons.lang3.StringUtils; 027import org.apache.maven.scm.CommandParameters; 028import org.apache.maven.scm.ScmException; 029import org.apache.maven.scm.ScmFileSet; 030import org.apache.maven.scm.ScmResult; 031import org.apache.maven.scm.command.AbstractCommand; 032import org.apache.maven.scm.command.info.InfoItem; 033import org.apache.maven.scm.command.info.InfoScmResult; 034import org.apache.maven.scm.provider.ScmProviderRepository; 035import org.apache.maven.scm.provider.git.command.GitCommand; 036import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; 037import org.eclipse.jgit.api.Git; 038import org.eclipse.jgit.lib.Constants; 039import org.eclipse.jgit.lib.ObjectId; 040import org.eclipse.jgit.lib.PersonIdent; 041import org.eclipse.jgit.lib.Repository; 042import org.eclipse.jgit.revwalk.RevCommit; 043import org.eclipse.jgit.revwalk.RevSort; 044import org.eclipse.jgit.revwalk.RevWalk; 045import org.eclipse.jgit.treewalk.filter.AndTreeFilter; 046import org.eclipse.jgit.treewalk.filter.PathFilter; 047import org.eclipse.jgit.treewalk.filter.TreeFilter; 048 049/** 050 * @since 1.9.5 051 */ 052public class JGitInfoCommand extends AbstractCommand implements GitCommand { 053 @Override 054 protected ScmResult executeCommand( 055 ScmProviderRepository repository, ScmFileSet fileSet, CommandParameters parameters) throws ScmException { 056 File basedir = fileSet.getBasedir(); 057 Git git = null; 058 try { 059 git = JGitUtils.openRepo(basedir); 060 ObjectId objectId = git.getRepository().resolve(Constants.HEAD); 061 if (objectId == null) { 062 throw new ScmException("Cannot resolve HEAD in git repository at " + basedir); 063 } 064 065 List<InfoItem> infoItems = new LinkedList<>(); 066 if (fileSet.getFileList().isEmpty()) { 067 RevCommit headCommit = git.getRepository().parseCommit(objectId); 068 infoItems.add(getInfoItem(headCommit, fileSet.getBasedir())); 069 } else { 070 // iterate over all files 071 for (File file : JGitUtils.getWorkingCopyRelativePaths( 072 git.getRepository().getWorkTree(), fileSet)) { 073 infoItems.add(getInfoItem(git.getRepository(), objectId, file)); 074 } 075 } 076 return new InfoScmResult(infoItems, new ScmResult("JGit.resolve(HEAD)", "", objectId.toString(), true)); 077 } catch (Exception e) { 078 throw new ScmException("JGit resolve failure!", e); 079 } finally { 080 JGitUtils.closeRepo(git); 081 } 082 } 083 084 protected InfoItem getInfoItem(Repository repository, ObjectId headObjectId, File file) throws IOException { 085 RevCommit commit = getMostRecentCommitForPath(repository, headObjectId, JGitUtils.toNormalizedFilePath(file)); 086 return getInfoItem(commit, file); 087 } 088 089 protected InfoItem getInfoItem(RevCommit fileCommit, File file) { 090 InfoItem infoItem = new InfoItem(); 091 infoItem.setPath(file.getPath()); 092 infoItem.setRevision(StringUtils.trim(fileCommit.name())); 093 infoItem.setURL(file.toPath().toUri().toASCIIString()); 094 PersonIdent authorIdent = fileCommit.getAuthorIdent(); 095 infoItem.setLastChangedDateTime(authorIdent 096 .getWhen() 097 .toInstant() 098 .atZone(authorIdent.getTimeZone().toZoneId())); 099 infoItem.setLastChangedAuthor(authorIdent.getName() + " <" + authorIdent.getEmailAddress() + ">"); 100 return infoItem; 101 } 102 103 private RevCommit getMostRecentCommitForPath(Repository repository, ObjectId headObjectId, String path) 104 throws IOException { 105 RevCommit latestCommit = null; 106 try (RevWalk revWalk = new RevWalk(repository)) { 107 RevCommit headCommit = revWalk.parseCommit(headObjectId); 108 revWalk.markStart(headCommit); 109 revWalk.sort(RevSort.COMMIT_TIME_DESC); 110 revWalk.setTreeFilter(AndTreeFilter.create(PathFilter.create(path), TreeFilter.ANY_DIFF)); 111 latestCommit = revWalk.next(); 112 } 113 return latestCommit; 114 } 115}