KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > mappings > CVSSubscriberMergeContext


1 /*******************************************************************************
2  * Copyright (c) 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.ccvs.ui.mappings;
12
13 import java.util.*;
14
15 import org.eclipse.core.resources.*;
16 import org.eclipse.core.runtime.*;
17 import org.eclipse.core.runtime.jobs.ISchedulingRule;
18 import org.eclipse.team.core.Team;
19 import org.eclipse.team.core.diff.IDiff;
20 import org.eclipse.team.core.diff.IThreeWayDiff;
21 import org.eclipse.team.core.mapping.*;
22 import org.eclipse.team.core.mapping.provider.MergeStatus;
23 import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
24 import org.eclipse.team.core.subscribers.Subscriber;
25 import org.eclipse.team.core.subscribers.SubscriberMergeContext;
26 import org.eclipse.team.internal.ccvs.core.*;
27 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
28 import org.eclipse.team.internal.ccvs.core.resources.EclipseSynchronizer;
29 import org.eclipse.team.internal.ccvs.core.syncinfo.ResourceSyncInfo;
30 import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
31 import org.eclipse.team.internal.ccvs.ui.Policy;
32 import org.eclipse.team.internal.core.mapping.DelegatingStorageMerger;
33
34 public abstract class CVSSubscriberMergeContext extends SubscriberMergeContext {
35
36     private static final IStorageMerger MERGER = new DelegatingStorageMerger() {
37         protected IStorageMerger findMerger(IStorage target) throws CoreException {
38             IStorageMerger storageMerger = super.findMerger(target);
39             if (storageMerger == null) {
40                 if (target instanceof IFile) {
41                     IFile file = (IFile) target;
42                     if (isText(file))
43                         storageMerger = getTextMerger();
44                 }
45             }
46             return storageMerger;
47         }
48
49         protected int getType(IStorage target) {
50             if (target instanceof IFile) {
51                 IFile file = (IFile) target;
52                 if (isText(file))
53                     return Team.TEXT;
54                 return Team.BINARY;
55             }
56             return super.getType(target);
57         }
58         
59         private boolean isText(IFile file) {
60             try {
61                 ICVSFile cvsFile = CVSWorkspaceRoot.getCVSFileFor(file);
62                 byte[] syncBytes = cvsFile.getSyncBytes();
63                 if (syncBytes != null)
64                     return !ResourceSyncInfo.isBinary(syncBytes);
65             } catch (CVSException e) {
66                 CVSUIPlugin.log(e);
67             }
68             return false;
69         }
70     };
71     
72     protected CVSSubscriberMergeContext(Subscriber subscriber, ISynchronizationScopeManager manager) {
73         super(subscriber, manager);
74     }
75     
76     /* (non-Javadoc)
77      * @see org.eclipse.team.core.mapping.MergeContext#run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor)
78      */

79     public void run(final IWorkspaceRunnable runnable, final ISchedulingRule rule, int flags, IProgressMonitor monitor) throws CoreException {
80         super.run(new IWorkspaceRunnable() {
81             public void run(IProgressMonitor monitor) throws CoreException {
82                 EclipseSynchronizer.getInstance().run(rule, new ICVSRunnable(){
83                     public void run(IProgressMonitor monitor) throws CVSException {
84                         try {
85                             runnable.run(monitor);
86                         } catch (CoreException e) {
87                             throw CVSException.wrapException(e);
88                         }
89                     }
90                 }, monitor);
91             }
92         
93         }, rule, flags, monitor);
94     }
95     
96     /* (non-Javadoc)
97      * @see org.eclipse.team.core.mapping.MergeContext#getMergeRule(org.eclipse.core.resources.IResource)
98      */

99     public ISchedulingRule getMergeRule(IDiff node) {
100         // Return the project since that is what the EclipseSynchronize needs
101
return getDiffTree().getResource(node).getProject();
102     }
103     
104     /* (non-Javadoc)
105      * @see org.eclipse.team.core.mapping.provider.MergeContext#makeInSync(org.eclipse.team.core.diff.IDiff, org.eclipse.core.runtime.IProgressMonitor)
106      */

107     protected void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException {
108         markAsMerged(diff, true, monitor);
109     }
110     
111     /* (non-Javadoc)
112      * @see org.eclipse.team.core.mapping.IMergeContext#reject(org.eclipse.team.core.diff.IDiff, org.eclipse.core.runtime.IProgressMonitor)
113      */

114     public void reject(IDiff diff, IProgressMonitor monitor) throws CoreException {
115         markAsMerged(diff, false, monitor);
116     }
117     
118     public IStatus merge(final IDiff[] diffs, final boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException {
119         final IStatus[] result = new IStatus[] { Status.OK_STATUS };
120         if (diffs.length > 0)
121             run(new IWorkspaceRunnable() {
122                 public void run(IProgressMonitor monitor) throws CoreException {
123                     result[0] = internalMerge(diffs, ignoreLocalChanges, monitor);
124                 }
125             }, getMergeRule(diffs), IWorkspace.AVOID_UPDATE, monitor);
126         return result[0];
127     }
128
129     private IStatus internalMerge(final IDiff[] diffs, final boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException {
130         
131         // The list of diffs that add or change the local file
132
List fileChanges = new ArrayList();
133         // The list of folders diffs
134
List folderDiffs = new ArrayList();
135         // The list of diffs that will result in the deletion of
136
// the local file
137
List fileDeletions = new ArrayList();
138         
139         for (int i = 0; i < diffs.length; i++) {
140             IDiff diff = diffs[i];
141             IResource resource = ResourceDiffTree.getResourceFor(diff);
142             if (resource.getType() == IResource.FILE) {
143                 if (isIncomingDeletion(diff, ignoreLocalChanges)) {
144                     fileDeletions.add(diff);
145                 } else {
146                     fileChanges.add(diff);
147                 }
148             } else {
149                 folderDiffs.add(diff);
150             }
151         }
152         
153         if (fileDeletions.isEmpty() && fileChanges.isEmpty() && folderDiffs.isEmpty())
154             return Status.OK_STATUS;
155         
156         // We do deletions first so that case changes can occur on platforms that are no case sensitive
157
int ticks = (fileDeletions.size() + fileChanges.size()) * 100;
158         try {
159             monitor.beginTask(null, ticks);
160             List result = new ArrayList();
161             if (!fileDeletions.isEmpty()) {
162                 IStatus status = CVSSubscriberMergeContext.super.merge(
163                         (IDiff[]) fileDeletions.toArray(new IDiff[fileDeletions.size()]),
164                         ignoreLocalChanges,
165                         Policy.subMonitorFor(monitor, 100 * fileDeletions.size()));
166                 if (!status.isOK()) {
167                     if (status.isMultiStatus()) {
168                         result.addAll(Arrays.asList(status.getChildren()));
169                     } else {
170                         result.add(status);
171                     }
172                 }
173             }
174             if (!fileChanges.isEmpty()) {
175                 IStatus status = CVSSubscriberMergeContext.super.merge(
176                         (IDiff[]) fileChanges.toArray(new IDiff[fileChanges.size()]),
177                         ignoreLocalChanges,
178                         Policy.subMonitorFor(monitor, 100 * fileChanges.size()));
179                 if (!status.isOK()) {
180                     if (status.isMultiStatus()) {
181                         result.addAll(Arrays.asList(status.getChildren()));
182                     } else {
183                         result.add(status);
184                     }
185                 }
186             }
187             if (!folderDiffs.isEmpty()) {
188                 // Order the diffs so empty added children will get deleted before their parents are visited
189
Collections.sort(folderDiffs, new Comparator() {
190                     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
191                         return ((IDiff)o2).getPath().toString().compareTo(((IDiff)o1).getPath().toString());
192                     }
193                 });
194                 for (Iterator iter = folderDiffs.iterator(); iter.hasNext();) {
195                     IDiff diff = (IDiff) iter.next();
196                     IResource resource = ResourceDiffTree.getResourceFor(diff);
197                     IDiff currentDiff = getSubscriber().getDiff(resource);
198                     merge(currentDiff, ignoreLocalChanges, monitor);
199                 }
200             }
201             if (result.isEmpty())
202                 return Status.OK_STATUS;
203             if (result.size() == 1)
204                 return (IStatus)result.get(0);
205             return new MergeStatus(CVSUIPlugin.ID, ((IStatus)result.get(0)).getMessage(), getFailedFiles(result));
206         } finally {
207             monitor.done();
208         }
209     }
210
211     private boolean isIncomingDeletion(IDiff diff, boolean ignoreLocalChanges) {
212         if (diff instanceof IThreeWayDiff) {
213             IThreeWayDiff twd = (IThreeWayDiff) diff;
214             if (twd.getKind() == IDiff.REMOVE && twd.getDirection() == IThreeWayDiff.INCOMING)
215                 return true;
216             IDiff remoteChange = twd.getRemoteChange();
217             if (ignoreLocalChanges && remoteChange != null)
218                 return isIncomingDeletion(remoteChange, ignoreLocalChanges);
219             IDiff localChange = twd.getLocalChange();
220             if (ignoreLocalChanges && localChange != null)
221                 return isIncomingDeletion(localChange, ignoreLocalChanges);
222             return false;
223         }
224         if (diff instanceof IResourceDiff) {
225             IResourceDiff rd = (IResourceDiff) diff;
226             return (ignoreLocalChanges || getMergeType() == ISynchronizationContext.TWO_WAY) && rd.getAfterState() == null;
227         }
228         return false;
229     }
230
231     private IFile[] getFailedFiles(List result) {
232         List failures = new ArrayList();
233         for (Iterator iter = result.iterator(); iter.hasNext();) {
234             IStatus status = (IStatus) iter.next();
235             if (status instanceof MergeStatus) {
236                 MergeStatus ms = (MergeStatus) status;
237                 failures.addAll(Arrays.asList(ms.getConflictingFiles()));
238             }
239         }
240         return (IFile[]) failures.toArray(new IFile[failures.size()]);
241     }
242     
243     public Object JavaDoc getAdapter(Class JavaDoc adapter) {
244         if (adapter == IStorageMerger.class)
245             return MERGER;
246         return super.getAdapter(adapter);
247     }
248
249 }
250
Popular Tags