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 * See LICENSE for the full license text, also available.
11 *******************************************************************************/
12 package org
.spearce
.egit
.core
.op
;
15 import java
.io
.IOException
;
16 import java
.lang
.reflect
.InvocationTargetException
;
17 import java
.net
.URISyntaxException
;
18 import java
.util
.Collection
;
20 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
21 import org
.eclipse
.core
.runtime
.NullProgressMonitor
;
22 import org
.eclipse
.core
.runtime
.SubProgressMonitor
;
23 import org
.eclipse
.jface
.operation
.IRunnableWithProgress
;
24 import org
.eclipse
.osgi
.util
.NLS
;
25 import org
.spearce
.egit
.core
.CoreText
;
26 import org
.spearce
.egit
.core
.EclipseGitProgressTransformer
;
27 import org
.spearce
.jgit
.errors
.NotSupportedException
;
28 import org
.spearce
.jgit
.errors
.TransportException
;
29 import org
.spearce
.jgit
.lib
.Commit
;
30 import org
.spearce
.jgit
.lib
.Constants
;
31 import org
.spearce
.jgit
.lib
.GitIndex
;
32 import org
.spearce
.jgit
.lib
.Ref
;
33 import org
.spearce
.jgit
.lib
.RefUpdate
;
34 import org
.spearce
.jgit
.lib
.Repository
;
35 import org
.spearce
.jgit
.lib
.RepositoryConfig
;
36 import org
.spearce
.jgit
.lib
.Tree
;
37 import org
.spearce
.jgit
.lib
.WorkDirCheckout
;
38 import org
.spearce
.jgit
.transport
.FetchResult
;
39 import org
.spearce
.jgit
.transport
.RefSpec
;
40 import org
.spearce
.jgit
.transport
.RemoteConfig
;
41 import org
.spearce
.jgit
.transport
.Transport
;
42 import org
.spearce
.jgit
.transport
.URIish
;
45 * Clones a repository from a remote location to a local location.
47 public class CloneOperation
implements IRunnableWithProgress
{
48 private final URIish uri
;
50 private final boolean allSelected
;
52 private final Collection
<Ref
> selectedBranches
;
54 private final File workdir
;
56 private final String branch
;
58 private final String remoteName
;
60 private Repository local
;
62 private RemoteConfig remoteConfig
;
64 private FetchResult fetchResult
;
67 * Create a new clone operation.
70 * remote we should fetch from.
72 * true when all branches have to be fetched (indicates wildcard
73 * in created fetch refspec), false otherwise.
74 * @param selectedBranches
75 * collection of branches to fetch. Ignored when allSelected is
78 * working directory to clone to. The directory may or may not
81 * branch to initially clone from.
83 * name of created remote config as source remote (typically
86 public CloneOperation(final URIish uri
, final boolean allSelected
,
87 final Collection
<Ref
> selectedBranches
, final File workdir
,
88 final String branch
, final String remoteName
) {
90 this.allSelected
= allSelected
;
91 this.selectedBranches
= selectedBranches
;
92 this.workdir
= workdir
;
94 this.remoteName
= remoteName
;
97 public void run(final IProgressMonitor pm
)
98 throws InvocationTargetException
, InterruptedException
{
99 final IProgressMonitor monitor
;
101 monitor
= new NullProgressMonitor();
106 monitor
.beginTask(NLS
.bind(CoreText
.CloneOperation_title
, uri
),
109 doInit(new SubProgressMonitor(monitor
, 100));
110 doFetch(new SubProgressMonitor(monitor
, 4000));
111 doCheckout(new SubProgressMonitor(monitor
, 900));
115 } catch (final Exception e
) {
117 if (monitor
.isCanceled())
118 throw new InterruptedException();
120 throw new InvocationTargetException(e
);
126 private void closeLocal() {
133 private void doInit(final IProgressMonitor monitor
)
134 throws URISyntaxException
, IOException
{
135 monitor
.setTaskName("Initializing local repository");
137 final File gitdir
= new File(workdir
, ".git");
138 local
= new Repository(gitdir
);
140 local
.writeSymref(Constants
.HEAD
, branch
);
142 remoteConfig
= new RemoteConfig(local
.getConfig(), remoteName
);
143 remoteConfig
.addURI(uri
);
145 final String dst
= Constants
.R_REMOTES
+ remoteConfig
.getName();
146 RefSpec wcrs
= new RefSpec();
147 wcrs
= wcrs
.setForceUpdate(true);
148 wcrs
= wcrs
.setSourceDestination(Constants
.R_HEADS
+ "*", dst
+ "/*");
151 remoteConfig
.addFetchRefSpec(wcrs
);
153 for (final Ref ref
: selectedBranches
)
154 if (wcrs
.matchSource(ref
))
155 remoteConfig
.addFetchRefSpec(wcrs
.expandFromSource(ref
));
158 // we're setting up for a clone with a checkout
159 local
.getConfig().setBoolean("core", null, "bare", false);
161 remoteConfig
.update(local
.getConfig());
163 // branch is like 'Constants.R_HEADS + branchName', we need only
164 // the 'branchName' part
165 String branchName
= branch
.substring(Constants
.R_HEADS
.length());
167 // setup the default remote branch for branchName
168 local
.getConfig().setString(RepositoryConfig
.BRANCH_SECTION
,
169 branchName
, "remote", remoteName
);
170 local
.getConfig().setString(RepositoryConfig
.BRANCH_SECTION
,
171 branchName
, "merge", branch
);
173 local
.getConfig().save();
176 private void doFetch(final IProgressMonitor monitor
)
177 throws NotSupportedException
, TransportException
{
178 final Transport tn
= Transport
.open(local
, remoteConfig
);
180 final EclipseGitProgressTransformer pm
;
181 pm
= new EclipseGitProgressTransformer(monitor
);
182 fetchResult
= tn
.fetch(pm
, null);
188 private void doCheckout(final IProgressMonitor monitor
) throws IOException
{
189 final Ref head
= fetchResult
.getAdvertisedRef(branch
);
190 if (head
== null || head
.getObjectId() == null)
193 final GitIndex index
= new GitIndex(local
);
194 final Commit mapCommit
= local
.mapCommit(head
.getObjectId());
195 final Tree tree
= mapCommit
.getTree();
197 final WorkDirCheckout co
;
199 u
= local
.updateRef(Constants
.HEAD
);
200 u
.setNewObjectId(mapCommit
.getCommitId());
203 monitor
.setTaskName("Checking out files");
204 co
= new WorkDirCheckout(local
, local
.getWorkDir(), index
, tree
);
206 monitor
.setTaskName("Writing index");
210 private static void delete(final File d
) {
211 if (d
.isDirectory()) {
212 final File
[] items
= d
.listFiles();
214 for (final File c
: items
)