1 package org.apache.maven.scm.provider.git.jgit.command.checkout;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.scm.ScmException;
23 import org.apache.maven.scm.ScmFile;
24 import org.apache.maven.scm.ScmFileSet;
25 import org.apache.maven.scm.ScmFileStatus;
26 import org.apache.maven.scm.ScmTag;
27 import org.apache.maven.scm.ScmVersion;
28 import org.apache.maven.scm.command.checkout.AbstractCheckOutCommand;
29 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
30 import org.apache.maven.scm.command.remoteinfo.RemoteInfoScmResult;
31 import org.apache.maven.scm.provider.ScmProviderRepository;
32 import org.apache.maven.scm.provider.git.command.GitCommand;
33 import org.apache.maven.scm.provider.git.jgit.command.JGitUtils;
34 import org.apache.maven.scm.provider.git.jgit.command.branch.JGitBranchCommand;
35 import org.apache.maven.scm.provider.git.jgit.command.remoteinfo.JGitRemoteInfoCommand;
36 import org.apache.maven.scm.provider.git.repository.GitScmProviderRepository;
37 import org.codehaus.plexus.util.StringUtils;
38 import org.eclipse.jgit.api.CloneCommand;
39 import org.eclipse.jgit.api.Git;
40 import org.eclipse.jgit.lib.Constants;
41 import org.eclipse.jgit.lib.ProgressMonitor;
42 import org.eclipse.jgit.revwalk.RevCommit;
43 import org.eclipse.jgit.revwalk.RevWalk;
44 import org.eclipse.jgit.storage.file.WindowCacheConfig;
45 import org.eclipse.jgit.transport.CredentialsProvider;
46 import org.eclipse.jgit.treewalk.TreeWalk;
47
48 import java.io.File;
49 import java.util.ArrayList;
50 import java.util.List;
51 import java.util.Set;
52
53
54
55
56
57
58 public class JGitCheckOutCommand
59 extends AbstractCheckOutCommand
60 implements GitCommand
61 {
62
63
64
65
66
67
68 protected CheckOutScmResult executeCheckOutCommand( ScmProviderRepository repo, ScmFileSet fileSet,
69 ScmVersion version, boolean recursive )
70 throws ScmException
71 {
72 GitScmProviderRepository repository = (GitScmProviderRepository) repo;
73
74 if ( GitScmProviderRepository.PROTOCOL_FILE.equals( repository.getFetchInfo().getProtocol() )
75 && repository.getFetchInfo().getPath().indexOf( fileSet.getBasedir().getPath() ) >= 0 )
76 {
77 throw new ScmException( "remote repository must not be the working directory" );
78 }
79
80 Git git = null;
81 try
82 {
83
84 ProgressMonitor monitor = JGitUtils.getMonitor( getLogger() );
85
86 String branch = version != null ? version.getName() : null;
87
88 if ( StringUtils.isBlank( branch ) )
89 {
90 branch = Constants.MASTER;
91 }
92
93 getLogger().debug( "try checkout of branch: " + branch );
94
95 if ( !fileSet.getBasedir().exists() || !( new File( fileSet.getBasedir(), ".git" ).exists() ) )
96 {
97 if ( fileSet.getBasedir().exists() )
98 {
99
100 fileSet.getBasedir().delete();
101 }
102
103
104 WindowCacheConfig cfg = new WindowCacheConfig();
105 cfg.setPackedGitMMAP( false );
106 cfg.install();
107
108
109 CredentialsProvider credentials = JGitUtils.getCredentials( (GitScmProviderRepository) repo );
110 getLogger().info( "cloning [" + branch + "] to " + fileSet.getBasedir() );
111 CloneCommand command = Git.cloneRepository().setURI( repository.getFetchUrl() );
112 command.setCredentialsProvider( credentials ).setBranch( branch ).setDirectory( fileSet.getBasedir() );
113 command.setProgressMonitor( monitor );
114 git = command.call();
115 }
116
117 JGitRemoteInfoCommand remoteInfoCommand = new JGitRemoteInfoCommand();
118 remoteInfoCommand.setLogger( getLogger() );
119 RemoteInfoScmResult result = remoteInfoCommand.executeRemoteInfoCommand( repository, fileSet, null );
120
121 if ( git == null )
122 {
123 git = Git.open( fileSet.getBasedir() );
124 }
125
126 if ( fileSet.getBasedir().exists() && new File( fileSet.getBasedir(), ".git" ).exists()
127 && result.getBranches().size() > 0 )
128 {
129
130 CredentialsProvider credentials = JGitUtils.prepareSession( getLogger(), git, repository );
131
132 if ( version != null && StringUtils.isNotEmpty( version.getName() ) && ( version instanceof ScmTag ) )
133 {
134
135
136
137
138
139 getLogger().debug( "fetch..." );
140 git.fetch().setCredentialsProvider( credentials ).setProgressMonitor( monitor ).call();
141 }
142 else
143 {
144 getLogger().debug( "pull..." );
145 git.pull().setCredentialsProvider( credentials ).setProgressMonitor( monitor ).call();
146 }
147 }
148
149 Set<String> localBranchNames = JGitBranchCommand.getShortLocalBranchNames( git );
150 if ( version instanceof ScmTag )
151 {
152 getLogger().info( "checkout tag [" + branch + "] at " + fileSet.getBasedir() );
153 git.checkout().setName( branch ).call();
154 }
155 else if ( localBranchNames.contains( branch ) )
156 {
157 getLogger().info( "checkout [" + branch + "] at " + fileSet.getBasedir() );
158 git.checkout().setName( branch ).call();
159 }
160 else
161 {
162 getLogger().info( "checkout remote branch [" + branch + "] at " + fileSet.getBasedir() );
163 git.checkout().setName( branch ).setCreateBranch( true ).setStartPoint( Constants.DEFAULT_REMOTE_NAME
164 + "/" + branch ).call();
165 }
166
167 RevWalk revWalk = new RevWalk( git.getRepository() );
168 RevCommit commit = revWalk.parseCommit( git.getRepository().resolve( Constants.HEAD ) );
169 revWalk.release();
170
171 final TreeWalk walk = new TreeWalk( git.getRepository() );
172 walk.reset();
173 walk.setRecursive( true );
174 walk.addTree( commit.getTree() );
175
176 List<ScmFile> listedFiles = new ArrayList<ScmFile>();
177 while ( walk.next() )
178 {
179 listedFiles.add( new ScmFile( walk.getPathString(), ScmFileStatus.CHECKED_OUT ) );
180 }
181 walk.release();
182
183 getLogger().debug( "current branch: " + git.getRepository().getBranch() );
184
185 return new CheckOutScmResult( "checkout via JGit", listedFiles );
186 }
187 catch ( Exception e )
188 {
189 throw new ScmException( "JGit checkout failure!", e );
190 }
191 finally
192 {
193 JGitUtils.closeRepo( git );
194 }
195 }
196
197 }