KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > ccvs > ui > operations > DiffOperation


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 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.operations;
12
13 import java.io.*;
14 import java.util.*;
15
16 import org.eclipse.compare.patch.WorkspacePatcherUI;
17 import org.eclipse.core.resources.*;
18 import org.eclipse.core.resources.mapping.ResourceMapping;
19 import org.eclipse.core.runtime.*;
20 import org.eclipse.core.runtime.jobs.Job;
21 import org.eclipse.jface.dialogs.IDialogConstants;
22 import org.eclipse.jface.dialogs.MessageDialog;
23 import org.eclipse.osgi.util.NLS;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.team.internal.ccvs.core.*;
26 import org.eclipse.team.internal.ccvs.core.client.*;
27 import org.eclipse.team.internal.ccvs.core.client.Command.LocalOption;
28 import org.eclipse.team.internal.ccvs.core.client.listeners.DiffListener;
29 import org.eclipse.team.internal.ccvs.core.connection.CVSCommunicationException;
30 import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot;
31 import org.eclipse.team.internal.ccvs.ui.*;
32 import org.eclipse.team.internal.ccvs.ui.Policy;
33 import org.eclipse.ui.IWorkbenchPart;
34
35 public abstract class DiffOperation extends SingleCommandOperation {
36
37     private static final int UNIFIED_FORMAT = 0;
38     private static final int CONTEXT_FORMAT = 1;
39     private static final int STANDARD_FORMAT = 2;
40     
41     protected boolean isMultiPatch;
42     protected boolean includeFullPathInformation;
43     protected PrintStream stream;
44     protected IPath patchRoot;
45     protected boolean patchHasContents;
46     protected boolean patchHasNewFiles;
47     
48     /* see bug 116427 */
49     private Object JavaDoc destination = null;
50     
51     /* see bug 159894 */
52     private class CustomizableEOLPrintStream extends PrintStream{
53
54         private boolean error = false;
55         
56         private String JavaDoc defaultLineEnding = "\n"; //$NON-NLS-1$
57

58         public CustomizableEOLPrintStream(PrintStream openStream) {
59             super(openStream);
60             if(CVSProviderPlugin.getPlugin().isUsePlatformLineend()){
61                 defaultLineEnding = System.getProperty("line.separator"); //$NON-NLS-1$
62
}
63         }
64         
65         public boolean checkError() {
66             return error || super.checkError();
67         }
68
69         public void println() {
70             try{
71                 write(defaultLineEnding.getBytes());
72             } catch (IOException e){
73                 error = true;
74             }
75         }
76         
77         public void println(boolean x) {
78             print(x);
79             println();
80         }
81         
82         public void println(char x) {
83             print(x);
84             println();
85         }
86
87         public void println(char[] x) {
88             print(x);
89             println();
90         }
91
92         public void println(double x) {
93             print(x);
94             println();
95         }
96
97         public void println(float x) {
98             print(x);
99             println();
100         }
101
102         public void println(int x) {
103             print(x);
104             println();
105         }
106
107         public void println(long x) {
108             print(x);
109             println();
110         }
111
112         public void println(Object JavaDoc x) {
113             print(x);
114             println();
115         }
116         
117         public void println(String JavaDoc x) {
118             print(x);
119             println();
120         }
121     }
122     
123     public DiffOperation(IWorkbenchPart part, ResourceMapping[] mappings, LocalOption[] options, boolean isMultiPatch, boolean includeFullPathInformation, IPath patchRoot, Object JavaDoc destination) {
124         super(part, mappings, options);
125         this.isMultiPatch = isMultiPatch;
126         this.includeFullPathInformation=includeFullPathInformation;
127         this.patchRoot=patchRoot;
128         this.patchHasContents=false;
129         this.patchHasNewFiles=false;
130         this.destination = destination;
131     }
132     
133     protected boolean shouldRun(){
134         if (super.shouldRun() == false){
135             return false;
136         }
137         Job[] jobs = Job.getJobManager().find(destination);
138         if(jobs.length != 0){
139             MessageDialog question = new MessageDialog(getShell(),
140                     CVSUIMessages.DiffOperation_CreatePatchConflictTitle, null,
141                     NLS.bind(CVSUIMessages.DiffOperation_CreatePatchConflictMessage, destination.toString()),
142                     MessageDialog.QUESTION,
143                     new String JavaDoc[]{IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL},
144                     1);
145             if(question.open() == 0){
146                 Job.getJobManager().cancel(destination);
147             } else {
148                 return false;
149             }
150         }
151         return true;
152     }
153     
154     public void execute(IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
155         try {
156             stream = new CustomizableEOLPrintStream(openStream());
157             if (isMultiPatch){
158                 stream.println(WorkspacePatcherUI.getWorkspacePatchHeader());
159             }
160             super.execute(monitor);
161         } finally {
162             if (stream != null) {
163                 stream.close();
164             }
165         }
166     }
167  
168     /**
169      * Open and return a stream for the diff output.
170      * @return a stream for the diff output
171      */

172     protected abstract PrintStream openStream() throws CVSException;
173
174     protected void execute(CVSTeamProvider provider, IResource[] resources, boolean recurse, IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
175         
176         //add this project to the total projects encountered
177
final HashSet newFiles = new HashSet(); //array of ICVSResource - need HashSet to guard for duplicate entries
178
final HashSet existingFiles = new HashSet(); //array of IResource - need HashSet to guard for duplicate entries
179

180         monitor.beginTask(null,100);
181         final IProgressMonitor subMonitor = Policy.subMonitorFor(monitor,10);
182         for (int i = 0; i < resources.length; i++) {
183             IResource resource = resources[i];
184             ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(resource);
185             cvsResource.accept(new ICVSResourceVisitor() {
186                 public void visitFile(ICVSFile file) throws CVSException {
187                     if (!(file.isIgnored())) {
188                         if (!file.isManaged() || file.getSyncInfo().isAdded() ){
189                             //this is a new file
190
if (file.exists())
191                                 newFiles.add(file);
192                         }else if (file.isModified(subMonitor)){
193                             existingFiles.add(file.getIResource());
194                         }
195                     }
196                 }
197                 
198                 public void visitFolder(ICVSFolder folder) throws CVSException {
199                     // Even if we are not supposed to recurse we still need to go into
200
// the root directory.
201
if (!folder.exists() || folder.isIgnored() ) {
202                         return;
203                     }
204                     
205                     folder.acceptChildren(this);
206                     
207                 }
208             }, recurse);
209         }
210         subMonitor.done();
211         
212         //Check options
213
//Append our diff output to the server diff output.
214
// Our diff output includes new files and new files in new directories.
215
int format = STANDARD_FORMAT;
216     
217         LocalOption[] localoptions = getLocalOptions(recurse);
218         for (int i = 0; i < localoptions.length; i++) {
219             LocalOption option = localoptions[i];
220             if (option.equals(Diff.UNIFIED_FORMAT) ||
221                 isMultiPatch) {
222                 format = UNIFIED_FORMAT;
223             } else if (option.equals(Diff.CONTEXT_FORMAT)) {
224                 format = CONTEXT_FORMAT;
225             }
226         }
227         
228         boolean haveAddedProjectHeader=false;
229         
230         if (!existingFiles.isEmpty()){
231             if (isMultiPatch && !haveAddedProjectHeader){
232                 haveAddedProjectHeader=true;
233                 IProject project=resources[0].getProject();
234                 stream.println(WorkspacePatcherUI.getWorkspacePatchProjectHeader(project));
235             }
236             try{
237                 super.execute(provider, (IResource[]) existingFiles.toArray(new IResource[existingFiles.size()]), recurse, Policy.subMonitorFor(monitor, 90));
238             } catch(CVSCommunicationException ex){ // see bug 123430
239
CVSUIPlugin.openError(getShell(), null, null, ex, CVSUIPlugin.PERFORM_SYNC_EXEC | CVSUIPlugin.LOG_OTHER_EXCEPTIONS);
240             } catch (CVSException ex){
241                 //ignore
242
}
243         }
244         
245         if (!newFiles.isEmpty() && Diff.INCLUDE_NEWFILES.isElementOf(localoptions)){
246             //Set new file to flag to let us know that we have added something to the current patch
247
patchHasNewFiles=true;
248             
249             if (isMultiPatch &&!haveAddedProjectHeader){
250                 haveAddedProjectHeader=true;
251                 IProject project=resources[0].getProject();
252                 stream.println(WorkspacePatcherUI.getWorkspacePatchProjectHeader(project));
253             }
254             
255             for (Iterator iter = newFiles.iterator(); iter.hasNext();) {
256                 ICVSFile cvsFile = (ICVSFile) iter.next();
257                 addFileToDiff(getNewFileRoot(cvsFile), cvsFile,stream,format);
258             }
259         }
260         
261         monitor.done();
262     }
263
264     private ICVSFolder getNewFileRoot(ICVSFile cvsFile) {
265         ICVSFolder patchRootFolder = getPatchRootFolder();
266         if (patchRootFolder != null)
267             return patchRootFolder;
268         return CVSWorkspaceRoot.getCVSFolderFor(cvsFile.getIResource().getProject());
269     }
270     
271     protected IStatus executeCommand(Session session, CVSTeamProvider provider, ICVSResource[] resources, boolean recurse, IProgressMonitor monitor) throws CVSException, InterruptedException JavaDoc {
272         
273         DiffListener diffListener = new DiffListener(stream);
274         
275         IStatus status = Command.DIFF.execute(session,
276                             Command.NO_GLOBAL_OPTIONS,
277                             getLocalOptions(recurse),
278                             resources,
279                             diffListener,
280                             monitor);
281         
282         //Once any run of the Diff commands reports that it has written something to the stream, the patch
283
//in its entirety is considered non-empty - until then keep trying to set the flag.
284
if (!patchHasContents)
285             patchHasContents = diffListener.wroteToStream();
286
287         return status;
288     }
289
290     protected String JavaDoc getTaskName(CVSTeamProvider provider) {
291         return NLS.bind(CVSUIMessages.DiffOperation_0, new String JavaDoc[]{provider.getProject().getName()});
292     }
293
294     protected String JavaDoc getTaskName() {
295         return CVSUIMessages.DiffOperation_1;
296     }
297     
298     private void addFileToDiff(ICVSFolder patchRoot, ICVSFile file, PrintStream printStream, int format) throws CVSException {
299         
300         String JavaDoc nullFilePrefix = ""; //$NON-NLS-1$
301
String JavaDoc newFilePrefix = ""; //$NON-NLS-1$
302
String JavaDoc positionInfo = ""; //$NON-NLS-1$
303
String JavaDoc linePrefix = ""; //$NON-NLS-1$
304

305         String JavaDoc pathString=""; //$NON-NLS-1$
306

307         
308         //get the path string for this file
309
pathString= file.getRelativePath(patchRoot);
310     
311         int lines = 0;
312         BufferedReader fileReader = new BufferedReader(new InputStreamReader(file.getContents()));
313         try {
314             while (fileReader.readLine() != null) {
315                 lines++;
316             }
317         } catch (IOException e) {
318             throw CVSException.wrapException(file.getIResource(), NLS.bind(CVSMessages.CVSTeamProvider_errorAddingFileToDiff, new String JavaDoc[] { pathString }), e);
319         } finally {
320             try {
321                 fileReader.close();
322             } catch (IOException e1) {
323                 //ignore
324
}
325         }
326             
327         // Ignore empty files
328
if (lines == 0)
329             return;
330         
331         switch (format) {
332         case UNIFIED_FORMAT:
333             nullFilePrefix = "--- "; //$NON-NLS-1$
334
newFilePrefix = "+++ "; //$NON-NLS-1$
335
positionInfo = "@@ -0,0 +1," + lines + " @@" ; //$NON-NLS-1$ //$NON-NLS-2$
336
linePrefix = "+"; //$NON-NLS-1$
337
break;
338             
339         case CONTEXT_FORMAT :
340             nullFilePrefix = "*** "; //$NON-NLS-1$
341
newFilePrefix = "--- "; //$NON-NLS-1$
342
positionInfo = "--- 1," + lines + " ----"; //$NON-NLS-1$ //$NON-NLS-2$
343
linePrefix = "+ "; //$NON-NLS-1$
344
break;
345             
346         default :
347             positionInfo = "0a1," + lines; //$NON-NLS-1$
348
linePrefix = "> "; //$NON-NLS-1$
349
break;
350         }
351         
352         fileReader = new BufferedReader(new InputStreamReader(file.getContents()));
353         try {
354                 
355             printStream.println("Index: " + pathString); //$NON-NLS-1$
356
printStream.println("==================================================================="); //$NON-NLS-1$
357
printStream.println("RCS file: " + pathString); //$NON-NLS-1$
358
printStream.println("diff -N " + pathString); //$NON-NLS-1$
359

360             
361             if (format != STANDARD_FORMAT) {
362                 printStream.println(nullFilePrefix + "/dev/null 1 Jan 1970 00:00:00 -0000"); //$NON-NLS-1$
363
// Technically this date should be the local file date but nobody really cares.
364
printStream.println(newFilePrefix + pathString + " 1 Jan 1970 00:00:00 -0000"); //$NON-NLS-1$
365
}
366             
367             if (format == CONTEXT_FORMAT) {
368                 printStream.println("***************"); //$NON-NLS-1$
369
printStream.println("*** 0 ****"); //$NON-NLS-1$
370
}
371             
372             printStream.println(positionInfo);
373             
374             for (int i = 0; i < lines; i++) {
375                 printStream.print(linePrefix);
376                 printStream.println(fileReader.readLine());
377             }
378         } catch (IOException e) {
379             throw CVSException.wrapException(file.getIResource(), NLS.bind(CVSMessages.CVSTeamProvider_errorAddingFileToDiff, new String JavaDoc[] { pathString }), e);
380         } finally {
381             try {
382                 fileReader.close();
383             } catch (IOException e1) {
384             }
385         }
386     }
387
388     public void setStream(PrintStream stream) {
389         this.stream = new CustomizableEOLPrintStream(stream);
390     }
391
392     protected void reportEmptyDiff() {
393         CVSUIPlugin.openDialog(getShell(), new CVSUIPlugin.IOpenableInShell() {
394             public void open(Shell shell) {
395                 MessageDialog.openInformation(
396                     shell,
397                     CVSUIMessages.GenerateCVSDiff_noDiffsFoundTitle,
398                     CVSUIMessages.GenerateCVSDiff_noDiffsFoundMsg);
399             }
400         }, CVSUIPlugin.PERFORM_SYNC_EXEC);
401      }
402     
403     protected ICVSFolder getLocalRoot(CVSTeamProvider provider) throws CVSException {
404         ICVSFolder root = getPatchRootFolder();
405         if (root != null)
406             return root;
407         return super.getLocalRoot(provider);
408     }
409
410     private ICVSFolder getPatchRootFolder() {
411         if (!isMultiPatch &&
412             !includeFullPathInformation){
413             //Check to see if the selected patchRoot has enough segments to consider it a folder/resource
414
//if not just get the project
415

416             IResource patchFolder = null;
417             IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
418             if (patchRoot.segmentCount() > 1){
419                 patchFolder = root.getFolder(patchRoot);
420             } else {
421                 patchFolder = root.getProject(patchRoot.toString());
422             }
423         
424             ICVSResource cvsResource = CVSWorkspaceRoot.getCVSResourceFor(patchFolder);
425             if (!cvsResource.isFolder()) {
426                 cvsResource = cvsResource.getParent();
427             }
428             return (ICVSFolder) cvsResource;
429         }
430         return null;
431     }
432     
433     /* (non-Javadoc)
434      * @see org.eclipse.team.internal.ccvs.ui.operations.RepositoryProviderOperation#consultModelsForMappings()
435      */

436     public boolean consultModelsForMappings() {
437         return false;
438     }
439     
440     public boolean belongsTo(Object JavaDoc family){
441         if(family != null && family.equals(destination))
442             return true;
443         return super.belongsTo(family);
444     }
445
446 }
447
Popular Tags