From: Marek Zawirski <marek.zawirski@gmail.com>
To: robin.rosenberg@dewire.com, spearce@spearce.org
Cc: git@vger.kernel.org, Marek Zawirski <marek.zawirski@gmail.com>
Subject: [EGIT PATCH 20/31] Move clone logic away from GitCloneWizard to CloneOperation
Date: Sun, 17 Aug 2008 22:44:01 +0200 [thread overview]
Message-ID: <1219005852-21496-21-git-send-email-marek.zawirski@gmail.com> (raw)
In-Reply-To: <1219005852-21496-20-git-send-email-marek.zawirski@gmail.com>
Clone logic was unnaturally splitted between GitCloneWizard and
CloneOperation classes. Now, repository initialization part is moved
to CloneOperation, so there is cleaner separation of responsibilties.
Failure handling is also improved, incompletely cloned repository
directory is removed before reporting problem to user.
Directory creation is problematic issue because of potential errors,
so it's keeped in GitCloneWizard.
Signed-off-by: Marek Zawirski <marek.zawirski@gmail.com>
---
.../org/spearce/egit/core/op/CloneOperation.java | 129 +++++++++++++++++---
.../src/org/spearce/egit/ui/UIText.java | 4 +
.../egit/ui/internal/clone/GitCloneWizard.java | 78 +++----------
.../src/org/spearce/egit/ui/uitext.properties | 1 +
4 files changed, 130 insertions(+), 82 deletions(-)
diff --git a/org.spearce.egit.core/src/org/spearce/egit/core/op/CloneOperation.java b/org.spearce.egit.core/src/org/spearce/egit/core/op/CloneOperation.java
index 656f3cb..531045b 100644
--- a/org.spearce.egit.core/src/org/spearce/egit/core/op/CloneOperation.java
+++ b/org.spearce.egit.core/src/org/spearce/egit/core/op/CloneOperation.java
@@ -3,6 +3,7 @@
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Roger C. Soares <rogersoares@intelinet.com.br>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -10,8 +11,11 @@
*******************************************************************************/
package org.spearce.egit.core.op;
+import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
+import java.net.URISyntaxException;
+import java.util.Collection;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
@@ -31,39 +35,71 @@ import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.lib.Tree;
import org.spearce.jgit.lib.WorkDirCheckout;
import org.spearce.jgit.transport.FetchResult;
+import org.spearce.jgit.transport.RefSpec;
import org.spearce.jgit.transport.RemoteConfig;
import org.spearce.jgit.transport.Transport;
+import org.spearce.jgit.transport.URIish;
/**
* Clones a repository from a remote location to a local location.
*/
public class CloneOperation implements IRunnableWithProgress {
- private final Repository local;
+ private static final String HEADS_PREFIX = Constants.HEADS_PREFIX;
- private final RemoteConfig remote;
+ private static final String REMOTES_PREFIX_S = Constants.REMOTES_PREFIX
+ + "/";
+
+ private final URIish uri;
+
+ private final boolean allSelected;
+
+ private final Collection<Ref> selectedBranches;
+
+ private final File workdir;
private final String branch;
+ private final String remoteName;
+
+ private Repository local;
+
+ private RemoteConfig remoteConfig;
+
private FetchResult fetchResult;
/**
* Create a new clone operation.
*
- * @param r
- * repository the checkout will happen within.
- * @param t
+ * @param uri
* remote we should fetch from.
- * @param b
+ * @param allSelected
+ * true when all branches have to be fetched (indicates wildcard
+ * in created fetch refspec), false otherwise.
+ * @param selectedBranches
+ * collection of branches to fetch. Ignored when allSelected is
+ * true.
+ * @param workdir
+ * working directory to clone to. The directory may or may not
+ * already exist.
+ * @param branch
* branch to initially clone from.
+ * @param remoteName
+ * name of created remote config as source remote (typically
+ * named "origin").
*/
- public CloneOperation(final Repository r, final RemoteConfig t,
- final String b) {
- local = r;
- remote = t;
- branch = b;
+ public CloneOperation(final URIish uri, final boolean allSelected,
+ final Collection<Ref> selectedBranches, final File workdir,
+ final String branch, final String remoteName) {
+ this.uri = uri;
+ this.allSelected = allSelected;
+ this.selectedBranches = selectedBranches;
+ this.workdir = workdir;
+ this.branch = branch;
+ this.remoteName = remoteName;
}
- public void run(final IProgressMonitor pm) throws InvocationTargetException {
+ public void run(final IProgressMonitor pm)
+ throws InvocationTargetException, InterruptedException {
final IProgressMonitor monitor;
if (pm == null)
monitor = new NullProgressMonitor();
@@ -71,21 +107,65 @@ public class CloneOperation implements IRunnableWithProgress {
monitor = pm;
try {
- monitor.beginTask(NLS.bind(CoreText.CloneOperation_title, remote
- .getURIs().get(0).toString()), 5000);
- doFetch(new SubProgressMonitor(monitor, 4000));
- doCheckout(new SubProgressMonitor(monitor, 1000));
- } catch (IOException e) {
- if (!monitor.isCanceled())
+ monitor.beginTask(NLS.bind(CoreText.CloneOperation_title, uri),
+ 5000);
+ try {
+ doInit(new SubProgressMonitor(monitor, 100));
+ doFetch(new SubProgressMonitor(monitor, 4000));
+ doCheckout(new SubProgressMonitor(monitor, 900));
+ } finally {
+ closeLocal();
+ }
+ } catch (final Exception e) {
+ delete(workdir);
+ if (monitor.isCanceled())
+ throw new InterruptedException();
+ else
throw new InvocationTargetException(e);
} finally {
monitor.done();
}
}
+ private void closeLocal() {
+ if (local != null) {
+ local.close();
+ local = null;
+ }
+ }
+
+ private void doInit(final IProgressMonitor monitor)
+ throws URISyntaxException, IOException {
+ monitor.setTaskName("Initializing local repository");
+
+ final File gitdir = new File(workdir, ".git");
+ local = new Repository(gitdir);
+ local.create();
+ local.writeSymref(Constants.HEAD, branch);
+
+ remoteConfig = new RemoteConfig(local.getConfig(), remoteName);
+ remoteConfig.addURI(uri);
+
+ final String dst = REMOTES_PREFIX_S + remoteConfig.getName();
+ RefSpec wcrs = new RefSpec();
+ wcrs = wcrs.setForceUpdate(true);
+ wcrs = wcrs.setSourceDestination(HEADS_PREFIX + "/*", dst + "/*");
+
+ if (allSelected) {
+ remoteConfig.addFetchRefSpec(wcrs);
+ } else {
+ for (final Ref ref : selectedBranches)
+ if (wcrs.matchSource(ref))
+ remoteConfig.addFetchRefSpec(wcrs.expandFromSource(ref));
+ }
+
+ remoteConfig.update(local.getConfig());
+ local.getConfig().save();
+ }
+
private void doFetch(final IProgressMonitor monitor)
throws NotSupportedException, TransportException {
- final Transport tn = Transport.open(local, remote);
+ final Transport tn = Transport.open(local, remoteConfig);
try {
final EclipseGitProgressTransformer pm;
pm = new EclipseGitProgressTransformer(monitor);
@@ -116,4 +196,15 @@ public class CloneOperation implements IRunnableWithProgress {
monitor.setTaskName("Writing index");
index.write();
}
+
+ private static void delete(final File d) {
+ if (d.isDirectory()) {
+ final File[] items = d.listFiles();
+ if (items != null) {
+ for (final File c : items)
+ delete(c);
+ }
+ }
+ d.delete();
+ }
}
\ No newline at end of file
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java
index 0d39440..9150832 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java
@@ -53,6 +53,9 @@ public class UIText extends NLS {
public static String GitCloneWizard_failed;
/** */
+ public static String GitCloneWizard_errorCannotCreate;
+
+ /** */
public static String RepositorySelectionPage_sourceSelectionTitle;
/** */
@@ -180,6 +183,7 @@ public class UIText extends NLS {
/** */
public static String ResourceHistory_toggleCommentFill;
+
/** */
public static String ResourceHistory_toggleRevDetail;
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java
index 9c1d691..efcf57f 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/clone/GitCloneWizard.java
@@ -10,9 +10,8 @@
package org.spearce.egit.ui.internal.clone;
import java.io.File;
-import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
-import java.net.URISyntaxException;
+import java.util.Collection;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
@@ -29,22 +28,13 @@ import org.spearce.egit.ui.Activator;
import org.spearce.egit.ui.UIIcons;
import org.spearce.egit.ui.UIText;
import org.spearce.egit.ui.internal.components.RepositorySelectionPage;
-import org.spearce.jgit.lib.Constants;
import org.spearce.jgit.lib.Ref;
-import org.spearce.jgit.lib.Repository;
-import org.spearce.jgit.transport.RefSpec;
-import org.spearce.jgit.transport.RemoteConfig;
import org.spearce.jgit.transport.URIish;
/**
* Import Git Repository Wizard. A front end to a git clone operation.
*/
public class GitCloneWizard extends Wizard implements IImportWizard {
- private static final String HEADS_PREFIX = Constants.HEADS_PREFIX;
-
- private static final String REMOTES_PREFIX_S = Constants.REMOTES_PREFIX
- + "/";
-
private RepositorySelectionPage cloneSource;
private SourceBranchPage validSource;
@@ -68,62 +58,35 @@ public class GitCloneWizard extends Wizard implements IImportWizard {
@Override
public boolean performFinish() {
- final URIish uri;
- final Repository db;
- final RemoteConfig origin;
-
- uri = cloneSource.getSelection().getURI();
-
+ final URIish uri = cloneSource.getSelection().getURI();
+ final boolean allSelected = validSource.isAllSelected();
+ final Collection<Ref> selectedBranches = validSource
+ .getSelectedBranches();
final File workdir = cloneDestination.getDestinationFile();
final String branch = cloneDestination.getInitialBranch();
- final File gitdir = new File(workdir, ".git");
- try {
- db = new Repository(gitdir);
- db.create();
- db.writeSymref(Constants.HEAD, branch);
+ final String remoteName = cloneDestination.getRemote();
- final String rn = cloneDestination.getRemote();
- origin = new RemoteConfig(db.getConfig(), rn);
- origin.addURI(uri);
-
- final String dst = REMOTES_PREFIX_S + origin.getName();
- RefSpec wcrs = new RefSpec();
- wcrs = wcrs.setForceUpdate(true);
- wcrs = wcrs.setSourceDestination(HEADS_PREFIX + "/*", dst + "/*");
-
- if (validSource.isAllSelected()) {
- origin.addFetchRefSpec(wcrs);
- } else {
- for (final Ref ref : validSource.getSelectedBranches())
- if (wcrs.matchSource(ref))
- origin.addFetchRefSpec(wcrs.expandFromSource(ref));
- }
-
- origin.update(db.getConfig());
- db.getConfig().save();
- } catch (IOException err) {
- Activator.logError(UIText.GitCloneWizard_failed, err);
+ if (!workdir.mkdirs()) {
+ final String errorMessage = NLS.bind(
+ UIText.GitCloneWizard_errorCannotCreate, workdir.getPath());
ErrorDialog.openError(getShell(), getWindowTitle(),
UIText.GitCloneWizard_failed, new Status(IStatus.ERROR,
- Activator.getPluginId(), 0, err.getMessage(), err));
- return false;
- } catch (URISyntaxException e) {
+ Activator.getPluginId(), 0, errorMessage, null));
+ // let's give user a chance to fix this minor problem
return false;
}
- final CloneOperation op = new CloneOperation(db, origin, branch);
+ final CloneOperation op = new CloneOperation(uri, allSelected,
+ selectedBranches, workdir, branch, remoteName);
final Job job = new Job(NLS.bind(UIText.GitCloneWizard_jobName, uri
.toString())) {
@Override
protected IStatus run(final IProgressMonitor monitor) {
try {
op.run(monitor);
- if (monitor.isCanceled()) {
- db.close();
- delete(workdir);
- return Status.CANCEL_STATUS;
- }
return Status.OK_STATUS;
+ } catch (InterruptedException e) {
+ return Status.CANCEL_STATUS;
} catch (InvocationTargetException e) {
Throwable thr = e.getCause();
return new Status(IStatus.ERROR, Activator.getPluginId(),
@@ -135,15 +98,4 @@ public class GitCloneWizard extends Wizard implements IImportWizard {
job.schedule();
return true;
}
-
- private static void delete(final File d) {
- if (d.isDirectory()) {
- final File[] items = d.listFiles();
- if (items != null) {
- for (final File c : items)
- delete(c);
- }
- }
- d.delete();
- }
}
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties
index 857568a..420b610 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/uitext.properties
@@ -30,6 +30,7 @@ ExistingOrNewPage_createInParent=Create repository in project's parent directory
GitCloneWizard_title=Import Git Repository
GitCloneWizard_jobName=Cloning from {0}
GitCloneWizard_failed=Git repository clone failed.
+GitCloneWizard_errorCannotCreate=Cannot create directory {0}.
RepositorySelectionPage_sourceSelectionTitle=Source Git Repository
RepositorySelectionPage_sourceSelectionDescription=Enter the location of the source repository.
--
1.5.6.3
next prev parent reply other threads:[~2008-08-17 20:46 UTC|newest]
Thread overview: 62+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-17 20:43 [EGIT PATCH 00/31] Push GUI, GUI improvements, various jgit stuff Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 01/31] Fix Repository.mapObject() for missing objects Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 02/31] Fix Repository isValidRefName() for empty names Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 03/31] Fix Repository.resolve() to not throw runtime exceptions Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 04/31] Document/fix Transport open method for specific case Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 05/31] Fix RefSpec javadoc regarding spec expanding Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 06/31] Make wildcard checking public in RefSpec Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 07/31] Add openAll() and applyConfig() methods to Transport Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 08/31] Add dryRun option to Transport and console push Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 09/31] Extract Transport findRemoteRefUpdatesFor() as static method Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 10/31] Improve javadoc of Transport push() Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 11/31] Clean up exception issues in RemoteRefUpdate Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 12/31] Add another RemoteRefUpdate constructor, useful for 2-stage push Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 13/31] Add getAllRemoteConfigs() to RemoteConfig Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 14/31] Add setFetchRefSpecs and setPushRefSpecs " Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 15/31] Add simple abbreviate() method to ObjectId Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 16/31] Remove debug/test console output from GitIndex Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 17/31] Fix typo in uitext.properties message Marek Zawirski
2008-08-17 20:43 ` [EGIT PATCH 18/31] Refactor/rewrite CloneSourcePage to universal RepositorySelectionPage Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 19/31] Clone wizard and related: refactor, clean-up, fixes or improvements Marek Zawirski
2008-08-17 20:44 ` Marek Zawirski [this message]
2008-08-17 20:44 ` [EGIT PATCH 21/31] Add canCreateSubdir() heuristic in CloneDestinationPage Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 22/31] Set FileDialog selection appropriately in clone wizard Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 23/31] Allow selecting empty dir " Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 24/31] Clone wizard: force dir to suggested path only if repo selection change Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 25/31] Create ListRemoteOperation for listing remote repo branches Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 26/31] Make Clone's SourceBranchPage more user-friendly Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 27/31] Add few EPL Eclipse icons Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 28/31] Checkbox images/screenshots Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 29/31] Universal GUI for specifications edition: RefSpecPanel and related Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 30/31] Add PushOperation to plugin Marek Zawirski
2008-08-17 20:44 ` [EGIT PATCH 31/31] Push GUI Marek Zawirski
2008-08-19 18:24 ` [EGIT PATCH 28/31] Checkbox images/screenshots Robin Rosenberg
2008-08-19 16:45 ` [EGIT PATCH 12/31] Add another RemoteRefUpdate constructor, useful for 2-stage push Shawn O. Pearce
2008-08-19 16:28 ` [EGIT PATCH 08/31] Add dryRun option to Transport and console push Shawn O. Pearce
2008-08-19 17:59 ` [EGIT PATCH 00/31] Push GUI, GUI improvements, various jgit stuff Shawn O. Pearce
2008-08-19 19:21 ` Robin Rosenberg
2008-08-20 2:42 ` Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 1/6] Remove DEFAULT_DRY_RUN constant from Transport Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 2/6] Emphasize that db is a local one in RemoteRefUpdate Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 3/6] Handle URIs parsing errors in PushAction better Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 4/6] Fix proposal provider for fetch in RefSpecPanel Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 5/6] Fix disappearing "save configuration" label in RefSpecPage Marek Zawirski
2008-08-20 2:57 ` [EGIT PATCH 6/6] Fix RefSpecPage formatting Marek Zawirski
2008-08-20 14:13 ` [EGIT PATCH 00/31] Push GUI, GUI improvements, various jgit stuff Shawn O. Pearce
2008-08-20 15:23 ` Git-aware Issue Tracking? Petr Baudis
2008-08-20 16:44 ` Shawn O. Pearce
2008-08-20 20:25 ` Robin Rosenberg
2008-08-21 8:47 ` Martin Langhoff
2008-08-20 18:52 ` Jakub Narebski
2008-08-21 8:30 ` Pierre Habouzit
2008-08-21 9:23 ` Jakub Narebski
2008-08-20 20:22 ` Mike Dalessio
2008-08-21 8:55 ` Imran M Yousuf
2008-08-25 13:59 ` [EGIT PATCH 00/31] Push GUI, GUI improvements, various jgit stuff Marek Zawirski
2008-08-25 14:24 ` Shawn O. Pearce
2008-08-21 20:12 ` Robin Rosenberg
2008-08-21 20:16 ` Shawn O. Pearce
2008-08-21 23:25 ` Robin Rosenberg
2008-08-22 3:05 ` Shawn O. Pearce
2008-08-25 14:13 ` Marek Zawirski
2008-08-25 14:15 ` Shawn O. Pearce
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1219005852-21496-21-git-send-email-marek.zawirski@gmail.com \
--to=marek.zawirski@gmail.com \
--cc=git@vger.kernel.org \
--cc=robin.rosenberg@dewire.com \
--cc=spearce@spearce.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).