Repository: maven-scm Updated Branches: refs/heads/master abea2d9c8 -> 037ba69bc
SCM-765 fix JGit provider to use the correct commiter/author when committing changes Project: http://git-wip-us.apache.org/repos/asf/maven-scm/repo Commit: http://git-wip-us.apache.org/repos/asf/maven-scm/commit/6a4ccf50 Tree: http://git-wip-us.apache.org/repos/asf/maven-scm/tree/6a4ccf50 Diff: http://git-wip-us.apache.org/repos/asf/maven-scm/diff/6a4ccf50 Branch: refs/heads/master Commit: 6a4ccf507b73d92d33ee050dac8e2d977f7fb245 Parents: 692b76a Author: imod <[email protected]> Authored: Fri Jul 18 00:45:07 2014 +0200 Committer: imod <[email protected]> Committed: Fri Jul 18 00:45:07 2014 +0200 ---------------------------------------------------------------------- .../command/checkin/JGitCheckInCommand.java | 155 +++++++++++- ...GitCheckInCommandCommitterAuthorTckTest.java | 246 +++++++++++++++++++ 2 files changed, 400 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/maven-scm/blob/6a4ccf50/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java index 98c0f98..7e91cf0 100644 --- a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/main/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommand.java @@ -33,15 +33,37 @@ import org.codehaus.plexus.util.StringUtils; import org.eclipse.jgit.api.AddCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.UserConfig; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.transport.RefSpec; import java.io.File; +import java.net.InetAddress; +import java.net.UnknownHostException; import java.util.Collections; import java.util.List; import java.util.Set; /** + * This provider uses the following strategy to discover the committer and author name/mail for a commit: + * <ol> + * <li>"maven-scm" section in .gitconfig</li> + * <li>"user" section in .gitconfig</li> + * <li>"username" passed to maven execution</li> + * <li>default git config (system user and hostname for email)</li> + * </ol> + * + * the "maven-scm" config can be configured like this: + * + * the user to be used:<br> + * <code>git config --global maven-scm.name "dude"</code> + * <br> + * <code>git config --global maven-scm.email "[email protected]"</code> + * <br> + * the default email domain to be used (will be used to create an email from the username passed to maven):<br> + * <code>git config --global maven-scm.maildomain "mycomp.com"</code> + * <br> + * * @author <a href="mailto:[email protected]">Mark Struberg</a> * @author Dominik Bartholdi (imod) * @since 1.9 @@ -50,6 +72,15 @@ public class JGitCheckInCommand extends AbstractCheckInCommand implements GitCommand { + + protected static final String GIT_MAVEN_SECTION = "maven-scm"; + + protected static final String GIT_USERNAME = "name"; + + protected static final String GIT_EMAIL = "email"; + + protected static final String GIT_MAILDOMAIN = "maildomain"; + /** * {@inheritDoc} */ @@ -96,7 +127,10 @@ public class JGitCheckInCommand List<ScmFile> checkedInFiles = Collections.emptyList(); if ( doCommit ) { - RevCommit commitRev = git.commit().setMessage( message ).call(); + UserInfo author = getAuthor(repo, git); + UserInfo committer = getCommitter(repo, git); + + RevCommit commitRev = git.commit().setMessage( message ).setAuthor(author.name, author.email).setCommitter(committer.name, committer.email).call(); getLogger().info( "commit done: " + commitRev.getShortMessage() ); checkedInFiles = JGitUtils.getFilesInCommit( git.getRepository(), commitRev ); if ( getLogger().isDebugEnabled() ) @@ -132,4 +166,123 @@ public class JGitCheckInCommand } } + private static final class UserInfo + { + final String name; + final String email; + + public UserInfo(String name, String email) + { + this.name = name; + this.email = email; + } + } + + private UserInfo getCommitter( ScmProviderRepository repo, Git git ) + { + // mvn scm git config + String committerName = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_USERNAME ); + + // git config + UserConfig user = git.getRepository().getConfig().get(UserConfig.KEY); + if ( StringUtils.isBlank( committerName ) && !user.isCommitterNameImplicit() ) + { + committerName = user.getCommitterName(); + } + + // mvn parameter + if ( StringUtils.isBlank( committerName ) ) + { + committerName = repo.getUser(); + } + + // git default + if ( StringUtils.isBlank( committerName ) ) + { + committerName = user.getCommitterName(); + } + + + // maven scm git config + String committerMail = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_EMAIL ); + + // git config + if ( StringUtils.isBlank( committerMail ) && !user.isCommitterEmailImplicit() ) + { + committerMail = user.getCommitterEmail(); + } + + if ( StringUtils.isBlank( committerMail ) ) + { + String defaultDomain = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_MAILDOMAIN ); + defaultDomain = StringUtils.isNotBlank( defaultDomain ) ? defaultDomain : getHostname(); + + // mvn parameter (constructed with username) or git default + committerMail = StringUtils.isNotBlank( repo.getUser() ) ? repo.getUser() + "@" + defaultDomain : user.getCommitterEmail(); + } + + return new UserInfo( committerName, committerMail ); + } + + private UserInfo getAuthor( ScmProviderRepository repo, Git git ) + { + // mvn scm config + String authorName = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_USERNAME ); + + // git config + UserConfig user = git.getRepository().getConfig().get(UserConfig.KEY); + if ( StringUtils.isBlank( authorName ) && !user.isAuthorNameImplicit() ) + { + authorName = user.getAuthorName(); + } + + // mvn parameter + if ( StringUtils.isBlank( authorName ) ) + { + authorName = repo.getUser(); + } + + // git default + if ( StringUtils.isBlank( authorName ) ) + { + authorName = user.getAuthorName(); + } + + // maven scm git config + String authorMail = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_EMAIL ); + + // git config + if ( StringUtils.isBlank( authorMail ) && !user.isAuthorEmailImplicit() ) + { + authorMail = user.getAuthorEmail(); + } + + if ( StringUtils.isBlank( authorMail ) ) + { + String defaultDomain = git.getRepository().getConfig().getString( GIT_MAVEN_SECTION, null, GIT_MAILDOMAIN ); + defaultDomain = StringUtils.isNotBlank( defaultDomain ) ? defaultDomain : getHostname(); + + // mvn parameter (constructed with username) or git default + authorMail = StringUtils.isNotBlank( repo.getUser() ) ? repo.getUser() + "@" + defaultDomain : user.getAuthorEmail(); + } + + return new UserInfo( authorName, authorMail ); + } + + private String getHostname() + { + String hostname; + try + { + InetAddress localhost = java.net.InetAddress.getLocalHost(); + hostname = localhost.getHostName(); + } + catch ( UnknownHostException e ) + { + getLogger().warn( "failed to resolve hostname to create mail address, defaulting to 'maven-scm-provider-jgit'" ); + hostname = "maven-scm-provider-jgit"; + } + return hostname; + } + } http://git-wip-us.apache.org/repos/asf/maven-scm/blob/6a4ccf50/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/test/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommandCommitterAuthorTckTest.java ---------------------------------------------------------------------- diff --git a/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/test/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommandCommitterAuthorTckTest.java b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/test/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommandCommitterAuthorTckTest.java new file mode 100644 index 0000000..260be1c --- /dev/null +++ b/maven-scm-providers/maven-scm-providers-git/maven-scm-provider-jgit/src/test/java/org/apache/maven/scm/provider/git/jgit/command/checkin/JGitCheckInCommandCommitterAuthorTckTest.java @@ -0,0 +1,246 @@ +package org.apache.maven.scm.provider.git.jgit.command.checkin; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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. + */ + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import org.apache.maven.scm.ScmException; +import org.apache.maven.scm.ScmFileSet; +import org.apache.maven.scm.command.add.AddScmResult; +import org.apache.maven.scm.command.checkin.CheckInScmResult; +import org.apache.maven.scm.provider.git.GitScmTestUtils; +import org.apache.maven.scm.provider.git.command.checkin.GitCheckInCommandTckTest; +import org.apache.maven.scm.provider.git.jgit.command.JGitUtils; +import org.apache.maven.scm.repository.ScmRepository; +import org.codehaus.plexus.util.IOUtil; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.StoredConfig; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.util.FileUtils; + +/** + * @author Dominik Bartholdi (imod) + */ +public class JGitCheckInCommandCommitterAuthorTckTest + extends GitCheckInCommandTckTest +{ + /** + * {@inheritDoc} + */ + public String getScmUrl() + throws Exception + { + return GitScmTestUtils.getScmUrl( getRepositoryRoot(), "jgit" ); + } + + @Override + protected void deleteDirectory( File directory ) + throws IOException + { + if( directory.exists() ) + { + FileUtils.delete( directory, FileUtils.RECURSIVE | FileUtils.RETRY ); + } + } + + @Override + public void testCheckInCommandTest() throws Exception + { + File fooJava = new File( getWorkingCopy(), "src/main/java/Foo.java" ); + assertFalse( "check Foo.java doesn't yet exist", fooJava.canRead() ); + + Git git = Git.open( getWorkingCopy() ); + + RevCommit head = getHeadCommit( git.getRepository() ); + // Mark created the test repo... + assertEquals( "Mark Struberg", head.getCommitterIdent().getName() ); + JGitUtils.closeRepo(git); + + createAndCommitFile( fooJava, null ); + + // change user in config + git = Git.open( getWorkingCopy() ); + StoredConfig config = git.getRepository().getConfig(); + unsetConfig(config); + config.setString( "user", null, "name", "Dominik" ); + config.setString( "user", null, "email", "[email protected]" ); + config.save(); + + // make a commit + createAndCommitFile( fooJava, null ); + + // check new commit is done with new user in config + head = getHeadCommit( git.getRepository() ); + assertEquals( "Dominik", head.getCommitterIdent().getName() ); + assertEquals( "Dominik", head.getAuthorIdent().getName() ); + assertEquals( "[email protected]", head.getAuthorIdent().getEmailAddress() ); + assertEquals( "[email protected]", head.getCommitterIdent().getEmailAddress() ); + JGitUtils.closeRepo( git ); + + + // change user in config + git = Git.open( getWorkingCopy() ); + config = git.getRepository().getConfig(); + unsetConfig(config); + config.setString( "user", null, "name", "dbartholdi" ); + config.save(); + + // make a change + createAndCommitFile( fooJava, null ); + + // check new commit is done with new user in config + head = getHeadCommit( git.getRepository() ); + assertEquals( "dbartholdi", head.getCommitterIdent().getName() ); + assertFalse( "no mail domain is configured, git system default should be used", head.getCommitterIdent().getEmailAddress().contains( "dbartholdi" ) ); + JGitUtils.closeRepo( git ); + + + + // set a user in the maven section of the git config + git = Git.open( getWorkingCopy() ); + config = git.getRepository().getConfig(); + unsetConfig(config); + config.setString( JGitCheckInCommand.GIT_MAVEN_SECTION, null, JGitCheckInCommand.GIT_USERNAME, "Dude" ); + config.setString( JGitCheckInCommand.GIT_MAVEN_SECTION, null, JGitCheckInCommand.GIT_EMAIL, "[email protected]" ); + config.save(); + + // make a change + createAndCommitFile( fooJava, null ); + + // check new commit is done with new maven user in config + head = getHeadCommit( git.getRepository() ); + assertEquals( "Dude", head.getCommitterIdent().getName() ); + assertEquals( "Dude", head.getAuthorIdent().getName() ); + assertEquals( "[email protected]", head.getCommitterIdent().getEmailAddress() ); + assertEquals( "[email protected]", head.getAuthorIdent().getEmailAddress() ); + JGitUtils.closeRepo( git ); + + + // unset a user and maven user but set default mail domain + git = Git.open( getWorkingCopy() ); + config = git.getRepository().getConfig(); + unsetConfig(config); + config.setString( JGitCheckInCommand.GIT_MAVEN_SECTION, null, JGitCheckInCommand.GIT_MAILDOMAIN, "comp.com" ); + config.save(); + + // make a change with an user on the commandline + createAndCommitFile( fooJava, "dude" ); + + // check new commit is done with new maven user in config + head = getHeadCommit( git.getRepository() ); + assertEquals( "dude", head.getCommitterIdent().getName() ); + assertEquals( "[email protected]", head.getCommitterIdent().getEmailAddress() ); + assertEquals( "dude", head.getAuthorIdent().getName() ); + assertEquals( "[email protected]", head.getAuthorIdent().getEmailAddress() ); + JGitUtils.closeRepo( git ); + + + // unset a user and full maven section + git = Git.open( getWorkingCopy() ); + config = git.getRepository().getConfig(); + unsetConfig(config); + config.save(); + config.getString("user", null, "name"); + + // make a change with an user on the commandline + createAndCommitFile( fooJava, "dundy" ); + + // check new commit is done with new maven user in config + head = getHeadCommit( git.getRepository() ); + assertEquals( "dundy", head.getCommitterIdent().getName() ); + assertEquals( "dundy", head.getAuthorIdent().getName() ); + assertTrue( "the maven user (from parameter) name must be in the committer mail when nothing else is configured", head.getCommitterIdent().getEmailAddress().contains( "dundy" ) ); + assertTrue( "the user name (from parameter) must be in the author mail when nothing else is configured", head.getAuthorIdent().getEmailAddress().contains( "dundy" ) ); + JGitUtils.closeRepo( git ); + } + + private void unsetConfig(StoredConfig config) { + config.unsetSection( "user", null ); + config.unset( "user", null, "name" ); + // somehow unset does not always work on "user" + config.setString("user", null, "name", null); + config.setString("user", null, "email", null); + config.unsetSection( JGitCheckInCommand.GIT_MAVEN_SECTION, null ); + } + + + + + private void createAndCommitFile(File file, String username) throws Exception, + ScmException, IOException { + createFooJava( file ); + + ScmRepository scmRepository = getScmRepository(); + scmRepository.getProviderRepository().setUser(username); + AddScmResult addResult = getScmManager().add( scmRepository, + new ScmFileSet( getWorkingCopy(), "**/*.java" ) ); + + assertResultIsSuccess( addResult ); + + CheckInScmResult result = + getScmManager().checkIn( scmRepository, new ScmFileSet( getWorkingCopy(), "**/Foo.java" ), "Commit message" ); + + assertResultIsSuccess( result ); + } + + + private RevCommit getHeadCommit(Repository repository) throws Exception + { + RevWalk rw = new RevWalk(repository); + AnyObjectId headId = repository.resolve(Constants.HEAD); + RevCommit head = rw.parseCommit(headId); + rw.release();; + return head; + } + + private void createFooJava( File fooJava ) + throws Exception + { + FileWriter output = new FileWriter( fooJava ); + + PrintWriter printer = new PrintWriter( output ); + try + { + printer.println( "public class Foo" ); + printer.println( "{" ); + + printer.println( " public void foo()" ); + printer.println( " {" ); + printer.println( " //" + System.currentTimeMillis() ); + printer.println( " int i = 10;" ); + printer.println( " }" ); + + printer.println( "}" ); + } + finally + { + IOUtil.close( output ); + IOUtil.close( printer ); + } + } + +}
