1 /*******************************************************************************
2 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
3 * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org>
4 * Copyright (C) 2008, Google Inc.
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *******************************************************************************/
11 package org
.eclipse
.egit
.core
;
13 import java
.io
.IOException
;
15 import org
.eclipse
.core
.resources
.IFile
;
16 import org
.eclipse
.core
.resources
.IFolder
;
17 import org
.eclipse
.core
.resources
.IProject
;
18 import org
.eclipse
.core
.resources
.IProjectDescription
;
19 import org
.eclipse
.core
.resources
.IResource
;
20 import org
.eclipse
.core
.resources
.team
.IMoveDeleteHook
;
21 import org
.eclipse
.core
.resources
.team
.IResourceTree
;
22 import org
.eclipse
.core
.runtime
.Assert
;
23 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
24 import org
.eclipse
.core
.runtime
.IStatus
;
25 import org
.eclipse
.core
.runtime
.Status
;
26 import org
.eclipse
.egit
.core
.project
.GitProjectData
;
27 import org
.eclipse
.egit
.core
.project
.RepositoryMapping
;
28 import org
.spearce
.jgit
.dircache
.DirCache
;
29 import org
.spearce
.jgit
.dircache
.DirCacheBuilder
;
30 import org
.spearce
.jgit
.dircache
.DirCacheEditor
;
31 import org
.spearce
.jgit
.dircache
.DirCacheEntry
;
33 class GitMoveDeleteHook
implements IMoveDeleteHook
{
34 private static final boolean I_AM_DONE
= true;
36 private static final boolean FINISH_FOR_ME
= false;
38 private final GitProjectData data
;
40 GitMoveDeleteHook(final GitProjectData d
) {
45 public boolean deleteFile(final IResourceTree tree
, final IFile file
,
46 final int updateFlags
, final IProgressMonitor monitor
) {
47 final boolean force
= (updateFlags
& IResource
.FORCE
) == IResource
.FORCE
;
48 if (!force
&& !tree
.isSynchronized(file
, IResource
.DEPTH_ZERO
))
51 final RepositoryMapping map
= RepositoryMapping
.getMapping(file
);
56 final DirCache dirc
= DirCache
.lock(map
.getRepository());
57 final int first
= dirc
.findEntry(map
.getRepoRelativePath(file
));
63 final DirCacheBuilder edit
= dirc
.builder();
66 final int next
= dirc
.nextEntry(first
);
67 if (next
< dirc
.getEntryCount())
68 edit
.keep(next
, dirc
.getEntryCount() - next
);
70 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(),
71 0, CoreText
.MoveDeleteHook_operationError
, null));
72 tree
.standardDeleteFile(file
, updateFlags
, monitor
);
73 } catch (IOException e
) {
74 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(), 0,
75 CoreText
.MoveDeleteHook_operationError
, e
));
80 public boolean deleteFolder(final IResourceTree tree
, final IFolder folder
,
81 final int updateFlags
, final IProgressMonitor monitor
) {
82 // Deleting a GIT repository which is in use is a pretty bad idea. To
83 // delete disconnect the team provider first.
85 if (data
.isProtected(folder
)) {
86 return cannotModifyRepository(tree
);
92 public boolean deleteProject(final IResourceTree tree
,
93 final IProject project
, final int updateFlags
,
94 final IProgressMonitor monitor
) {
95 // TODO: Note that eclipse thinks folders are real, while
100 public boolean moveFile(final IResourceTree tree
, final IFile srcf
,
101 final IFile dstf
, final int updateFlags
,
102 final IProgressMonitor monitor
) {
103 final boolean force
= (updateFlags
& IResource
.FORCE
) == IResource
.FORCE
;
104 if (!force
&& !tree
.isSynchronized(srcf
, IResource
.DEPTH_ZERO
))
107 final RepositoryMapping srcm
= RepositoryMapping
.getMapping(srcf
);
110 final RepositoryMapping dstm
= RepositoryMapping
.getMapping(dstf
);
113 final DirCache sCache
= DirCache
.lock(srcm
.getRepository());
114 final String sPath
= srcm
.getRepoRelativePath(srcf
);
115 final DirCacheEntry sEnt
= sCache
.getEntry(sPath
);
121 final DirCacheEditor sEdit
= sCache
.editor();
122 sEdit
.add(new DirCacheEditor
.DeletePath(sEnt
));
123 if (dstm
!= null && dstm
.getRepository() == srcm
.getRepository()) {
124 final String dPath
= srcm
.getRepoRelativePath(dstf
);
125 sEdit
.add(new DirCacheEditor
.PathEdit(dPath
) {
127 public void apply(final DirCacheEntry dEnt
) {
128 dEnt
.copyMetaData(sEnt
);
133 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(),
134 0, CoreText
.MoveDeleteHook_operationError
, null));
136 tree
.standardMoveFile(srcf
, dstf
, updateFlags
, monitor
);
137 } catch (IOException e
) {
138 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(), 0,
139 CoreText
.MoveDeleteHook_operationError
, e
));
144 public boolean moveFolder(final IResourceTree tree
, final IFolder srcf
,
145 final IFolder dstf
, final int updateFlags
,
146 final IProgressMonitor monitor
) {
147 final boolean force
= (updateFlags
& IResource
.FORCE
) == IResource
.FORCE
;
148 if (!force
&& !tree
.isSynchronized(srcf
, IResource
.DEPTH_ZERO
))
151 final RepositoryMapping srcm
= RepositoryMapping
.getMapping(srcf
);
154 final RepositoryMapping dstm
= RepositoryMapping
.getMapping(dstf
);
157 final DirCache sCache
= DirCache
.lock(srcm
.getRepository());
158 final String sPath
= srcm
.getRepoRelativePath(srcf
);
159 final DirCacheEntry
[] sEnt
= sCache
.getEntriesWithin(sPath
);
160 if (sEnt
.length
== 0) {
165 final DirCacheEditor sEdit
= sCache
.editor();
166 sEdit
.add(new DirCacheEditor
.DeleteTree(sPath
));
167 if (dstm
!= null && dstm
.getRepository() == srcm
.getRepository()) {
168 final String dPath
= srcm
.getRepoRelativePath(dstf
) + "/";
169 final int sPathLen
= sPath
.length() + 1;
170 for (final DirCacheEntry se
: sEnt
) {
171 final String p
= se
.getPathString().substring(sPathLen
);
172 sEdit
.add(new DirCacheEditor
.PathEdit(dPath
+ p
) {
174 public void apply(final DirCacheEntry dEnt
) {
175 dEnt
.copyMetaData(se
);
181 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(),
182 0, CoreText
.MoveDeleteHook_operationError
, null));
184 tree
.standardMoveFolder(srcf
, dstf
, updateFlags
, monitor
);
185 } catch (IOException e
) {
186 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(), 0,
187 CoreText
.MoveDeleteHook_operationError
, e
));
192 public boolean moveProject(final IResourceTree tree
, final IProject source
,
193 final IProjectDescription description
, final int updateFlags
,
194 final IProgressMonitor monitor
) {
195 // TODO: We should be able to do this without too much effort when the
196 // projects belong to the same Git repository.
197 return FINISH_FOR_ME
;
200 private boolean cannotModifyRepository(final IResourceTree tree
) {
201 tree
.failed(new Status(IStatus
.ERROR
, Activator
.getPluginId(), 0,
202 CoreText
.MoveDeleteHook_cannotModifyFolder
, null));