/*
* Copyright 2014 the original author or authors.
*
* 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 me.cmoz.gradle.snapshot;
import lombok.NonNull;
import lombok.SneakyThrows;
import org.gradle.api.Project;
import org.tmatesoft.hg.core.*;
import org.tmatesoft.hg.repo.HgRepository;
import javax.annotation.Nullable;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
/**
* An {@code SCMCommand} for the Mercurial Source Control Management (SCM) tool.
*/
class HgSCMCommand implements SCMCommand {
private static final String REPO_DIRNAME = ".hg";
private File repoDir;
public HgSCMCommand(final Project project) {
repoDir = SCMUtil.scanDir(project, REPO_DIRNAME);
}
@Override
@Nullable
public File getRepositoryDir() {
return repoDir;
}
@Override
@SneakyThrows({HgRepositoryNotFoundException.class, HgException.class})
public Commit getLatestCommit(@NonNull final String dateFormat) {
if (repoDir == null) {
throw new IllegalStateException("'.hg' folder could not be found.");
}
final HgRepoFacade repo = new HgRepoFacade();
repo.initFrom(repoDir);
final SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
final int lastRevision = repo.getRepository().getChangelog().getLastRevision();
if (lastRevision == HgRepository.NO_REVISION) {
throw new RuntimeException("Could not find any changesets in Hg repository.");
}
final HgLogCommand hgLogCommand = repo.createLogCommand();
hgLogCommand.range(lastRevision, lastRevision);
final List<HgChangeset> changesets = hgLogCommand.execute();
if (changesets.size() < 1) {
throw new RuntimeException("Could not find any changesets in Hg repository.");
}
final HgChangeset commit = changesets.get(0);
return Commit.builder()
.buildTime(sdf.format(new Date()))
.buildAuthorName("") // TODO: how to get hgrc user name?
.buildAuthorEmail("") // TODO: how to get hgrc email?
.branchName(commit.getBranch())
.commitId(commit.getNodeid().toString())
.commitTime(sdf.format(new Date(commit.getDate().getRawTime())))
.commitUserName(extractName(commit.getUser()))
.commitUserEmail(extractEmail(commit.getUser()))
.commitMessage(commit.getComment().trim())
.build();
}
/**
* Extracts a name from the {@code HgChangeset#getUser()} string format.
*
* @param user The user string obtained from {@code HgChangeset#getUser()}.
* @return The name from the user string or an empty string if one could not
* be found.
*/
private static String extractName(@NonNull final String user) {
final int endIndex = (user.indexOf('<') != -1)
? user.indexOf('<')
: user.length();
return user.substring(0, endIndex).trim();
}
/**
* Extracts an email address from the {@code HgChangeset#getUser()} string
* format.
*
* <p>This method attempts to handle the following malformed string formats:
* <pre>
* {@code
* Firstname <
* Firstname Lastname <
* Firstname Lastname <>
* Firstname Lastname <Email>
* Firstname Lastname >
* Firstname >
* }
* </pre>
*
* @param user The user string obtained from {@code HgChangeset#getUser()}.
* @return The email address from the user string or an empty string if one
* could not be found.
*/
private static String extractEmail(@NonNull final String user) {
final int beginIndex = ((user.indexOf('<') + 1) < user.length())
? (user.indexOf('<') + 1)
: user.length();
final int endIndex = (user.lastIndexOf('>') != -1)
? user.lastIndexOf('>')
: user.length();
return user.substring(beginIndex, endIndex).trim();
}
}