/**
* Yobi, Project Hosting SW
*
* Copyright 2013 NAVER Corp.
* http://yobi.io
*
* @Author Keesun Baik
*
* 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 actors;
import akka.actor.UntypedActor;
import models.PostReceiveMessage;
import models.Project;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import playRepository.GitRepository;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* This abstract implementation can be used to add after-receive jobs.
* To add a post hook, extends this classs and execute it with Akka
*
* @author Keesun Baik
* @see IssueReferredFromCommitEventActor
* @see CommitsNotificationActor
*/
public abstract class PostReceiveActor extends UntypedActor {
@Override
public void onReceive(Object message) {
if(!(message instanceof PostReceiveMessage)) {
return;
}
PostReceiveMessage cap = (PostReceiveMessage)message;
doReceive(cap);
}
abstract void doReceive(PostReceiveMessage cap);
class CommitAndRefNames {
List<RevCommit> commits = new ArrayList<>();
List<String> refNames = new ArrayList<>();
public List<RevCommit> getCommits() {
return commits;
}
public void setCommits(List<RevCommit> commits) {
this.commits = commits;
}
public List<String> getRefNames() {
return refNames;
}
public void setRefNames(List<String> refNames) {
this.refNames = refNames;
}
public void addAll(Collection<? extends RevCommit> revCommits) {
this.commits.addAll(revCommits);
}
public void add(String refName) {
this.refNames.add(refName);
}
}
protected CommitAndRefNames commitAndRefNames(PostReceiveMessage message) {
CommitAndRefNames car = new CommitAndRefNames();
for(ReceiveCommand command : message.getCommands()) {
if(isNewOrUpdateCommand(command)) {
car.addAll(parseCommitsFrom(command, message.getProject()));
car.add(command.getRefName());
}
}
return car;
}
protected boolean isNewOrUpdateCommand(ReceiveCommand command) {
List<ReceiveCommand.Type> allowdTypes = new ArrayList<>();
allowdTypes.add(ReceiveCommand.Type.CREATE);
allowdTypes.add(ReceiveCommand.Type.UPDATE);
allowdTypes.add(ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
return allowdTypes.contains(command.getType());
}
protected Collection<? extends RevCommit> parseCommitsFrom(ReceiveCommand command, Project project) {
Repository repository = GitRepository.buildGitRepository(project);
List<RevCommit> list = new ArrayList<>();
try {
ObjectId endRange = command.getNewId();
ObjectId startRange = command.getOldId();
RevWalk rw = new RevWalk(repository);
rw.markStart(rw.parseCommit(endRange));
if (startRange.equals(ObjectId.zeroId())) {
// maybe this is a tag or an orphan branch
list.add(rw.parseCommit(endRange));
rw.dispose();
return list;
} else {
rw.markUninteresting(rw.parseCommit(startRange));
}
for (RevCommit rev : rw) {
list.add(rev);
}
rw.dispose();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
}