1 /*******************************************************************************
2 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
3 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
4 * Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
5 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
6 * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
8 * All rights reserved. This program and the accompanying materials
9 * are made available under the terms of the Eclipse Public License v1.0
10 * which accompanies this distribution, and is available at
11 * http://www.eclipse.org/legal/epl-v10.html
12 *******************************************************************************/
13 package org
.eclipse
.egit
.core
.op
;
16 import java
.io
.IOException
;
17 import java
.lang
.reflect
.InvocationTargetException
;
18 import java
.net
.URISyntaxException
;
19 import java
.util
.Collection
;
21 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
22 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
23 import org
.eclipse
.core
.runtime
.SubProgressMonitor
;
24 import org
.eclipse
.egit
.core
.CoreText
;
25 import org
.eclipse
.egit
.core
.EclipseGitProgressTransformer
;
26 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
27 import org
.eclipse
.osgi
.util
.NLS
;
28 import org
.eclipse
.jgit
.errors
.NotSupportedException
;
29 import org
.eclipse
.jgit
.errors
.TransportException
;
30 import org
.eclipse
.jgit
.lib
.Commit
;
31 import org
.eclipse
.jgit
.lib
.Constants
;
32 import org
.eclipse
.jgit
.lib
.GitIndex
;
33 import org
.eclipse
.jgit
.lib
.Ref
;
34 import org
.eclipse
.jgit
.lib
.RefUpdate
;
35 import org
.eclipse
.jgit
.lib
.Repository
;
36 import org
.eclipse
.jgit
.lib
.RepositoryConfig
;
37 import org
.eclipse
.jgit
.lib
.Tree
;
38 import org
.eclipse
.jgit
.lib
.WorkDirCheckout
;
39 import org
.eclipse
.jgit
.transport
.FetchResult
;
40 import org
.eclipse
.jgit
.transport
.RefSpec
;
41 import org
.eclipse
.jgit
.transport
.RemoteConfig
;
42 import org
.eclipse
.jgit
.transport
.Transport
;
43 import org
.eclipse
.jgit
.transport
.URIish
;
46 * Clones a repository from a remote location to a local location.
48 public class CloneOperation
implements IRunnableWithProgress
{
49 private final URIish uri
;
51 private final boolean allSelected
;
53 private final Collection
<Ref
> selectedBranches
;
55 private final File workdir
;
57 private final File gitdir
;
59 private final String branch
;
61 private final String remoteName
;
63 private Repository local
;
65 private RemoteConfig remoteConfig
;
67 private FetchResult fetchResult
;
70 * Create a new clone operation.
73 * remote we should fetch from.
75 * true when all branches have to be fetched (indicates wildcard
76 * in created fetch refspec), false otherwise.
77 * @param selectedBranches
78 * collection of branches to fetch. Ignored when allSelected is
81 * working directory to clone to. The directory may or may not
84 * branch to initially clone from.
86 * name of created remote config as source remote (typically
89 public CloneOperation(final URIish uri
, final boolean allSelected
,
90 final Collection
<Ref
> selectedBranches
, final File workdir
,
91 final String branch
, final String remoteName
) {
93 this.allSelected
= allSelected
;
94 this.selectedBranches
= selectedBranches
;
95 this.workdir
= workdir
;
96 this.gitdir
= new File(workdir
, Constants
.DOT_GIT
);
98 this.remoteName
= remoteName
;
101 public void run(final IProgressMonitor pm
)
102 throws InvocationTargetException
, InterruptedException
{
103 final IProgressMonitor monitor
;
105 monitor
= new NullProgressMonitor();
110 monitor
.beginTask(NLS
.bind(CoreText
.CloneOperation_title
, uri
),
113 doInit(new SubProgressMonitor(monitor
, 100));
114 doFetch(new SubProgressMonitor(monitor
, 4000));
115 doCheckout(new SubProgressMonitor(monitor
, 900));
119 } catch (final Exception e
) {
121 if (monitor
.isCanceled())
122 throw new InterruptedException();
124 throw new InvocationTargetException(e
);
132 * @return The git directory which will contain the repository
134 public File
getGitDir() {
138 private void closeLocal() {
145 private void doInit(final IProgressMonitor monitor
)
146 throws URISyntaxException
, IOException
{
147 monitor
.setTaskName("Initializing local repository");
149 local
= new Repository(gitdir
);
152 final RefUpdate head
= local
.updateRef(Constants
.HEAD
);
153 head
.disableRefLog();
156 remoteConfig
= new RemoteConfig(local
.getConfig(), remoteName
);
157 remoteConfig
.addURI(uri
);
159 final String dst
= Constants
.R_REMOTES
+ remoteConfig
.getName();
160 RefSpec wcrs
= new RefSpec();
161 wcrs
= wcrs
.setForceUpdate(true);
162 wcrs
= wcrs
.setSourceDestination(Constants
.R_HEADS
+ "*", dst
+ "/*");
165 remoteConfig
.addFetchRefSpec(wcrs
);
167 for (final Ref ref
: selectedBranches
)
168 if (wcrs
.matchSource(ref
))
169 remoteConfig
.addFetchRefSpec(wcrs
.expandFromSource(ref
));
172 // we're setting up for a clone with a checkout
173 local
.getConfig().setBoolean("core", null, "bare", false);
175 remoteConfig
.update(local
.getConfig());
177 // branch is like 'Constants.R_HEADS + branchName', we need only
178 // the 'branchName' part
179 String branchName
= branch
.substring(Constants
.R_HEADS
.length());
181 // setup the default remote branch for branchName
182 local
.getConfig().setString(RepositoryConfig
.BRANCH_SECTION
,
183 branchName
, "remote", remoteName
);
184 local
.getConfig().setString(RepositoryConfig
.BRANCH_SECTION
,
185 branchName
, "merge", branch
);
187 local
.getConfig().save();
190 private void doFetch(final IProgressMonitor monitor
)
191 throws NotSupportedException
, TransportException
{
192 final Transport tn
= Transport
.open(local
, remoteConfig
);
194 final EclipseGitProgressTransformer pm
;
195 pm
= new EclipseGitProgressTransformer(monitor
);
196 fetchResult
= tn
.fetch(pm
, null);
202 private void doCheckout(final IProgressMonitor monitor
) throws IOException
{
203 final Ref head
= fetchResult
.getAdvertisedRef(branch
);
204 if (head
== null || head
.getObjectId() == null)
207 final GitIndex index
= new GitIndex(local
);
208 final Commit mapCommit
= local
.mapCommit(head
.getObjectId());
209 final Tree tree
= mapCommit
.getTree();
211 final WorkDirCheckout co
;
213 u
= local
.updateRef(Constants
.HEAD
);
214 u
.setNewObjectId(mapCommit
.getCommitId());
217 monitor
.setTaskName("Checking out files");
218 co
= new WorkDirCheckout(local
, local
.getWorkDir(), index
, tree
);
220 monitor
.setTaskName("Writing index");
224 private static void delete(final File d
) {
225 if (d
.isDirectory()) {
226 final File
[] items
= d
.listFiles();
228 for (final File c
: items
)