Multi-project connect to Git provider
[egit/imyousuf.git] / org.spearce.egit.core / src / org / spearce / egit / core / op / CloneOperation.java
blobf31940faa88f155b45f4b6d1a7cfb975a5a78f8e
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;
14 import java.io.File;
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;
44 /**
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;
66 /**
67 * Create a new clone operation.
69 * @param uri
70 * remote we should fetch from.
71 * @param allSelected
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
76 * true.
77 * @param workdir
78 * working directory to clone to. The directory may or may not
79 * already exist.
80 * @param branch
81 * branch to initially clone from.
82 * @param remoteName
83 * name of created remote config as source remote (typically
84 * named "origin").
86 public CloneOperation(final URIish uri, final boolean allSelected,
87 final Collection<Ref> selectedBranches, final File workdir,
88 final String branch, final String remoteName) {
89 this.uri = uri;
90 this.allSelected = allSelected;
91 this.selectedBranches = selectedBranches;
92 this.workdir = workdir;
93 this.branch = branch;
94 this.remoteName = remoteName;
97 public void run(final IProgressMonitor pm)
98 throws InvocationTargetException, InterruptedException {
99 final IProgressMonitor monitor;
100 if (pm == null)
101 monitor = new NullProgressMonitor();
102 else
103 monitor = pm;
105 try {
106 monitor.beginTask(NLS.bind(CoreText.CloneOperation_title, uri),
107 5000);
108 try {
109 doInit(new SubProgressMonitor(monitor, 100));
110 doFetch(new SubProgressMonitor(monitor, 4000));
111 doCheckout(new SubProgressMonitor(monitor, 900));
112 } finally {
113 closeLocal();
115 } catch (final Exception e) {
116 delete(workdir);
117 if (monitor.isCanceled())
118 throw new InterruptedException();
119 else
120 throw new InvocationTargetException(e);
121 } finally {
122 monitor.done();
126 private void closeLocal() {
127 if (local != null) {
128 local.close();
129 local = null;
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);
139 local.create();
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 + "/*");
150 if (allSelected) {
151 remoteConfig.addFetchRefSpec(wcrs);
152 } else {
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);
179 try {
180 final EclipseGitProgressTransformer pm;
181 pm = new EclipseGitProgressTransformer(monitor);
182 fetchResult = tn.fetch(pm, null);
183 } finally {
184 tn.close();
188 private void doCheckout(final IProgressMonitor monitor) throws IOException {
189 final Ref head = fetchResult.getAdvertisedRef(branch);
190 if (head == null || head.getObjectId() == null)
191 return;
193 final GitIndex index = new GitIndex(local);
194 final Commit mapCommit = local.mapCommit(head.getObjectId());
195 final Tree tree = mapCommit.getTree();
196 final RefUpdate u;
197 final WorkDirCheckout co;
199 u = local.updateRef(Constants.HEAD);
200 u.setNewObjectId(mapCommit.getCommitId());
201 u.forceUpdate();
203 monitor.setTaskName("Checking out files");
204 co = new WorkDirCheckout(local, local.getWorkDir(), index, tree);
205 co.checkout();
206 monitor.setTaskName("Writing index");
207 index.write();
210 private static void delete(final File d) {
211 if (d.isDirectory()) {
212 final File[] items = d.listFiles();
213 if (items != null) {
214 for (final File c : items)
215 delete(c);
218 d.delete();