KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > compare > internal > patch > Patcher


1 /*******************************************************************************
2  * Copyright (c) 2000, 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  * Martin Burger <m@rtin-burger.de> patch for #93810 and #93901
11  *******************************************************************************/

12 package org.eclipse.compare.internal.patch;
13
14 import java.io.*;
15 import java.util.*;
16
17 import org.eclipse.compare.internal.CompareUIPlugin;
18 import org.eclipse.compare.internal.Utilities;
19 import org.eclipse.compare.patch.PatchConfiguration;
20 import org.eclipse.compare.structuremergeviewer.Differencer;
21 import org.eclipse.core.resources.*;
22 import org.eclipse.core.runtime.*;
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.widgets.Shell;
25
26 /**
27  * A Patcher
28  * - knows how to parse various patch file formats into some in-memory structure,
29  * - holds onto the parsed data and the options to use when applying the patches,
30  * - knows how to apply the patches to files and folders.
31  */

32 public class Patcher {
33
34     static protected final String JavaDoc REJECT_FILE_EXTENSION= ".rej"; //$NON-NLS-1$
35

36     static protected final String JavaDoc MARKER_TYPE= "org.eclipse.compare.rejectedPatchMarker"; //$NON-NLS-1$
37

38     /**
39      * Property used to associate a patcher with a {@link PatchConfiguration}
40      */

41     public static final String JavaDoc PROP_PATCHER = "org.eclipse.compare.patcher"; //$NON-NLS-1$
42

43     // diff formats
44
// private static final int CONTEXT= 0;
45
// private static final int ED= 1;
46
// private static final int NORMAL= 2;
47
// private static final int UNIFIED= 3;
48

49     private FileDiff[] fDiffs;
50     private IResource fTarget;
51     // patch options
52
private Set disabledElements = new HashSet();
53     private Map diffResults = new HashMap();
54     private final Map contentCache = new HashMap();
55     private Set mergedHunks = new HashSet();
56
57     private final PatchConfiguration configuration;
58     private boolean fGenerateRejectFile = false;
59     
60     public Patcher() {
61         configuration = new PatchConfiguration();
62         configuration.setProperty(PROP_PATCHER, this);
63     }
64     
65     /*
66      * Returns an array of Diffs after a sucessfull call to <code>parse</code>.
67      * If <code>parse</code> hasn't been called returns <code>null</code>.
68      */

69     public FileDiff[] getDiffs() {
70         if (fDiffs == null)
71             return new FileDiff[0];
72         return fDiffs;
73     }
74     
75     public IPath getPath(FileDiff diff) {
76         return diff.getStrippedPath(getStripPrefixSegments(), isReversed());
77     }
78
79     /*
80      * Returns <code>true</code> if new value differs from old.
81      */

82     boolean setStripPrefixSegments(int strip) {
83         if (strip != getConfiguration().getPrefixSegmentStripCount()) {
84             getConfiguration().setPrefixSegmentStripCount(strip);
85             return true;
86         }
87         return false;
88     }
89     
90     int getStripPrefixSegments() {
91         return getConfiguration().getPrefixSegmentStripCount();
92     }
93     
94     /*
95      * Returns <code>true</code> if new value differs from old.
96      */

97     boolean setFuzz(int fuzz) {
98         if (fuzz != getConfiguration().getFuzz()) {
99             getConfiguration().setFuzz(fuzz);
100             return true;
101         }
102         return false;
103     }
104     
105     int getFuzz(){
106         return getConfiguration().getFuzz();
107     }
108         
109     /*
110      * Returns <code>true</code> if new value differs from old.
111      */

112     boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
113         if (ignoreWhitespace != getConfiguration().isIgnoreWhitespace()) {
114             getConfiguration().setIgnoreWhitespace(ignoreWhitespace);
115             return true;
116         }
117         return false;
118     }
119     
120     boolean isIgnoreWhitespace() {
121         return getConfiguration().isIgnoreWhitespace();
122     }
123     
124     public boolean isGenerateRejectFile() {
125         return fGenerateRejectFile;
126     }
127
128     public void setGenerateRejectFile(boolean generateRejectFile) {
129         fGenerateRejectFile = generateRejectFile;
130     }
131     
132     //---- parsing patch files
133

134     public void parse(IStorage storage) throws IOException, CoreException {
135         BufferedReader reader = createReader(storage);
136         try {
137             parse(reader);
138         } finally {
139             try {
140                 reader.close();
141             } catch (IOException e) { //ignored
142
}
143         }
144     }
145     
146     public static BufferedReader createReader(IStorage storage) throws CoreException {
147         return new BufferedReader(new InputStreamReader(storage.getContents()));
148     }
149     
150     public void parse(BufferedReader reader) throws IOException {
151         PatchReader patchReader= new PatchReader();
152         patchReader.parse(reader);
153         patchParsed(patchReader);
154     }
155
156     protected void patchParsed(PatchReader patchReader) {
157         fDiffs = patchReader.getDiffs();
158     }
159     
160     //---- applying a patch file
161

162     public void applyAll(IProgressMonitor pm, Shell shell, String JavaDoc title) throws CoreException {
163
164         final int WORK_UNIT= 10;
165         
166         int i;
167         
168         IFile singleFile= null; // file to be patched
169
IContainer container= null;
170         if (fTarget instanceof IContainer)
171             container= (IContainer) fTarget;
172         else if (fTarget instanceof IFile) {
173             singleFile= (IFile) fTarget;
174             container= singleFile.getParent();
175         } else {
176             Assert.isTrue(false);
177         }
178         
179         // get all files to be modified in order to call validateEdit
180
List list= new ArrayList();
181         if (singleFile != null)
182             list.add(singleFile);
183         else {
184             for (i= 0; i < fDiffs.length; i++) {
185                 FileDiff diff= fDiffs[i];
186                 if (isEnabled(diff)) {
187                     switch (diff.getDiffType(isReversed())) {
188                     case Differencer.CHANGE:
189                         list.add(createPath(container, getPath(diff)));
190                         break;
191                     }
192                 }
193             }
194         }
195         if (! Utilities.validateResources(list, shell, title))
196             return;
197         
198         if (pm != null) {
199             String JavaDoc message= PatchMessages.Patcher_Task_message;
200             pm.beginTask(message, fDiffs.length*WORK_UNIT);
201         }
202         
203         for (i= 0; i < fDiffs.length; i++) {
204             
205             int workTicks= WORK_UNIT;
206             
207             FileDiff diff= fDiffs[i];
208             if (isEnabled(diff)) {
209                 
210                 IPath path= getPath(diff);
211                 if (pm != null)
212                     pm.subTask(path.toString());
213             
214                 IFile file= singleFile != null
215                                 ? singleFile
216                                 : createPath(container, path);
217                     
218                 List failed= new ArrayList();
219                 
220                 int type= diff.getDiffType(isReversed());
221                 switch (type) {
222                 case Differencer.ADDITION:
223                     // patch it and collect rejected hunks
224
List result= apply(diff, file, true, failed);
225                     if (result != null)
226                         store(createString(isPreserveLineDelimeters(), result), file, new SubProgressMonitor(pm, workTicks));
227                     workTicks-= WORK_UNIT;
228                     break;
229                 case Differencer.DELETION:
230                     file.delete(true, true, new SubProgressMonitor(pm, workTicks));
231                     workTicks-= WORK_UNIT;
232                     break;
233                 case Differencer.CHANGE:
234                     // patch it and collect rejected hunks
235
result= apply(diff, file, false, failed);
236                     if (result != null)
237                         store(createString(isPreserveLineDelimeters(), result), file, new SubProgressMonitor(pm, workTicks));
238                     workTicks-= WORK_UNIT;
239                     break;
240                 }
241
242                 if (isGenerateRejectFile() && failed.size() > 0) {
243                     IPath pp = getRejectFilePath(path);
244                     file= createPath(container, pp);
245                     if (file != null) {
246                         store(getRejected(failed), file, pm);
247                         try {
248                             IMarker marker= file.createMarker(MARKER_TYPE);
249                             marker.setAttribute(IMarker.MESSAGE, PatchMessages.Patcher_Marker_message);
250                             marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
251                         } catch (CoreException ex) {
252                             // NeedWork
253
}
254                     }
255                 }
256             }
257             
258             if (pm != null) {
259                 if (pm.isCanceled())
260                     break;
261                 if (workTicks > 0)
262                     pm.worked(workTicks);
263             }
264         }
265     }
266
267     private IPath getRejectFilePath(IPath path) {
268         IPath pp= null;
269         if (path.segmentCount() > 1) {
270             pp= path.removeLastSegments(1);
271             pp= pp.append(path.lastSegment() + REJECT_FILE_EXTENSION);
272         } else
273             pp= new Path(path.lastSegment() + REJECT_FILE_EXTENSION);
274         return pp;
275     }
276     
277     /*
278      * Reads the contents from the given file and returns them as
279      * a List of lines.
280      */

281     public static List load(IStorage file, boolean create) {
282         List lines= null;
283         if (!create && file != null && exists(file)) {
284             // read current contents
285
String JavaDoc charset = Utilities.getCharset(file);
286             InputStream is= null;
287             try {
288                 is= file.getContents();
289                 
290                 Reader streamReader= null;
291                 try {
292                     streamReader= new InputStreamReader(is, charset);
293                 } catch (UnsupportedEncodingException x) {
294                     // use default encoding
295
streamReader= new InputStreamReader(is);
296                 }
297                 
298                 BufferedReader reader= new BufferedReader(streamReader);
299                 lines = readLines(reader);
300             } catch(CoreException ex) {
301                 // TODO
302
CompareUIPlugin.log(ex);
303             } finally {
304                 if (is != null)
305                     try {
306                         is.close();
307                     } catch(IOException ex) {
308                         // silently ignored
309
}
310             }
311         }
312         
313         if (lines == null)
314             lines= new ArrayList();
315         return lines;
316     }
317
318     private static boolean exists(IStorage file) {
319         if (file instanceof IFile) {
320             return ((IFile) file).exists();
321         }
322         return true;
323     }
324
325     private static List readLines(BufferedReader reader) {
326         List lines;
327         LineReader lr= new LineReader(reader);
328         if (!"carbon".equals(SWT.getPlatform())) //$NON-NLS-1$
329
lr.ignoreSingleCR();
330         lines= lr.readLines();
331         return lines;
332     }
333     
334     List apply(FileDiff diff, IFile file, boolean create, List failedHunks) {
335         FileDiffResult result = getDiffResult(diff);
336         List lines = Patcher.load(file, create);
337         result.patch(lines, null);
338         failedHunks.addAll(result.getFailedHunks());
339         if (hasCachedContents(diff)) {
340             // Used the cached contents since they would have been provided by the user
341
return getCachedLines(diff);
342         } else if (!result.hasMatches()) {
343             // Return null if there were no matches
344
return null;
345         }
346         return result.getLines();
347     }
348     
349     /*
350      * Converts the string into bytes and stores them in the given file.
351      */

352     protected void store(String JavaDoc contents, IFile file, IProgressMonitor pm) throws CoreException {
353
354         byte[] bytes;
355         try {
356             bytes= contents.getBytes(Utilities.getCharset(file));
357         } catch (UnsupportedEncodingException x) {
358             // uses default encoding
359
bytes= contents.getBytes();
360         }
361         
362         store(bytes,file, pm);
363     }
364
365     protected void store(byte[] bytes, IFile file, IProgressMonitor pm) throws CoreException {
366         InputStream is= new ByteArrayInputStream(bytes);
367         try {
368             if (file.exists()) {
369                 file.setContents(is, false, true, pm);
370             } else {
371                 file.create(is, false, pm);
372             }
373         } finally {
374             if (is != null)
375                 try {
376                     is.close();
377                 } catch(IOException ex) {
378                     // silently ignored
379
}
380         }
381     }
382
383     
384     
385     /*
386      * Concatenates all strings found in the given List.
387      */

388     public static String JavaDoc createString(boolean preserveLineDelimeters, List lines) {
389         StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
390         Iterator iter= lines.iterator();
391         if (preserveLineDelimeters) {
392             while (iter.hasNext())
393                 sb.append((String JavaDoc)iter.next());
394         } else {
395             String JavaDoc lineSeparator= System.getProperty("line.separator"); //$NON-NLS-1$
396
while (iter.hasNext()) {
397                 String JavaDoc line= (String JavaDoc)iter.next();
398                 int l= length(line);
399                 if (l < line.length()) { // line has delimiter
400
sb.append(line.substring(0, l));
401                     sb.append(lineSeparator);
402                 } else {
403                     sb.append(line);
404                 }
405             }
406         }
407         return sb.toString();
408     }
409
410     protected boolean isPreserveLineDelimeters() {
411         return false;
412     }
413
414     public static String JavaDoc getRejected(List failedHunks) {
415         if (failedHunks.size() <= 0)
416             return null;
417         
418         String JavaDoc lineSeparator= System.getProperty("line.separator"); //$NON-NLS-1$
419
StringBuffer JavaDoc sb= new StringBuffer JavaDoc();
420         Iterator iter= failedHunks.iterator();
421         while (iter.hasNext()) {
422             Hunk hunk= (Hunk) iter.next();
423             sb.append(hunk.getRejectedDescription());
424             sb.append(lineSeparator);
425             sb.append(hunk.getContent());
426         }
427         return sb.toString();
428     }
429     
430     /*
431      * Ensures that a file with the given path exists in
432      * the given container. Folder are created as necessary.
433      */

434     protected IFile createPath(IContainer container, IPath path) throws CoreException {
435         if (path.segmentCount() > 1) {
436             IContainer childContainer;
437             if (container instanceof IWorkspaceRoot) {
438                 IProject project = ((IWorkspaceRoot)container).getProject(path.segment(0));
439                 if (!project.exists())
440                     project.create(null);
441                 if (!project.isOpen())
442                     project.open(null);
443                 childContainer = project;
444             } else {
445                 IFolder f= container.getFolder(path.uptoSegment(1));
446                 if (!f.exists())
447                     f.create(false, true, null);
448                 childContainer = f;
449             }
450             return createPath(childContainer, path.removeFirstSegments(1));
451         }
452         // a leaf
453
return container.getFile(path);
454     }
455     
456     /*
457      * Returns the length (excluding a line delimiter CR, LF, CR/LF)
458      * of the given string.
459      */

460     /* package */ static int length(String JavaDoc s) {
461         int l= s.length();
462         if (l > 0) {
463             char c= s.charAt(l-1);
464             if (c == '\r')
465                 return l-1;
466             if (c == '\n') {
467                 if (l > 1 && s.charAt(l-2) == '\r')
468                     return l-2;
469                 return l-1;
470             }
471         }
472         return l;
473     }
474
475     public IResource getTarget() {
476         return fTarget;
477     }
478
479     public void setTarget(IResource target) {
480         fTarget= target;
481     }
482     
483
484     protected IFile getTargetFile(FileDiff diff) {
485         IPath path = diff.getStrippedPath(getStripPrefixSegments(), isReversed());
486         return existsInTarget(path);
487     }
488     
489     /**
490      * Iterates through all of the resources contained in the Patch Wizard target
491      * and looks to for a match to the passed in file
492      * @param path
493      * @return IFile which matches the passed in path or null if none found
494      */

495     public IFile existsInTarget(IPath path) {
496         if (fTarget instanceof IFile) { // special case
497
IFile file= (IFile) fTarget;
498             if (matches(file.getFullPath(), path))
499                 return file;
500         } else if (fTarget instanceof IContainer) {
501             IContainer c= (IContainer) fTarget;
502             if (c.exists(path))
503                 return c.getFile(path);
504         }
505         return null;
506     }
507
508     /**
509      * Returns true if path completely matches the end of fullpath
510      * @param fullpath
511      * @param path
512      * @return true if path matches, false otherwise
513      */

514     private boolean matches(IPath fullpath, IPath path) {
515         for (IPath p= fullpath; path.segmentCount()<=p.segmentCount(); p= p.removeFirstSegments(1)) {
516             if (p.equals(path))
517                 return true;
518         }
519         return false;
520     }
521
522     public int calculatePrefixSegmentCount() {
523         //Update prefix count - go through all of the diffs and find the smallest
524
//path segment contained in all diffs.
525
int length= 99;
526         if (fDiffs!=null)
527             for (int i= 0; i<fDiffs.length; i++) {
528                 FileDiff diff= fDiffs[i];
529                 length= Math.min(length, diff.segmentCount());
530             }
531         return length;
532     }
533     
534     public void addDiff(FileDiff newDiff){
535         FileDiff[] temp = new FileDiff[fDiffs.length + 1];
536         System.arraycopy(fDiffs,0, temp, 0, fDiffs.length);
537         temp[fDiffs.length] = newDiff;
538         fDiffs = temp;
539     }
540     
541     public void removeDiff(FileDiff diffToRemove){
542         FileDiff[] temp = new FileDiff[fDiffs.length - 1];
543         int counter = 0;
544         for (int i = 0; i < fDiffs.length; i++) {
545             if (fDiffs[i] != diffToRemove){
546                 temp[counter++] = fDiffs[i];
547             }
548         }
549         fDiffs = temp;
550     }
551     
552     public void setEnabled(Object JavaDoc element, boolean enabled) {
553         if (element instanceof DiffProject)
554             setEnabledProject((DiffProject) element, enabled);
555         if (element instanceof FileDiff)
556             setEnabledFile((FileDiff)element, enabled);
557         if (element instanceof Hunk)
558             setEnabledHunk((Hunk) element, enabled);
559     }
560     
561     private void setEnabledProject(DiffProject projectDiff, boolean enabled) {
562         FileDiff[] diffFiles = projectDiff.getFileDiffs();
563         for (int i = 0; i < diffFiles.length; i++) {
564             setEnabledFile(diffFiles[i], enabled);
565         }
566     }
567     
568     private void setEnabledFile(FileDiff fileDiff, boolean enabled) {
569         Hunk[] hunks = fileDiff.getHunks();
570         for (int i = 0; i < hunks.length; i++) {
571             setEnabledHunk(hunks[i], enabled);
572         }
573     }
574
575     private void setEnabledHunk(Hunk hunk, boolean enabled) {
576         if (enabled) {
577             disabledElements.remove(hunk);
578             FileDiff file = hunk.getParent();
579             disabledElements.remove(file);
580             DiffProject project = file.getProject();
581             if (project != null)
582                 disabledElements.remove(project);
583         } else {
584             disabledElements.add(hunk);
585             FileDiff file = hunk.getParent();
586             if (disabledElements.containsAll(Arrays.asList(file.getHunks()))) {
587                 disabledElements.add(file);
588                 DiffProject project = file.getProject();
589                 if (project != null
590                         && disabledElements.containsAll(Arrays.asList(project
591                                 .getFileDiffs())))
592                     disabledElements.add(project);
593             }
594         }
595     }
596
597     public boolean isEnabled(Object JavaDoc element) {
598         if (disabledElements.contains(element))
599             return false;
600         Object JavaDoc parent = getElementParent(element);
601         if (parent == null)
602             return true;
603         return isEnabled(parent);
604     }
605
606     protected Object JavaDoc getElementParent(Object JavaDoc element) {
607         if (element instanceof Hunk) {
608             Hunk hunk = (Hunk) element;
609             return hunk.getParent();
610         }
611         return null;
612     }
613     
614     /**
615      * Calculate the fuzz factor that will allow the most hunks to be matched.
616      * @param monitor a progress monitor
617      * @return the fuzz factor or <code>-1</code> if no hunks could be matched
618      */

619     public int guessFuzzFactor(IProgressMonitor monitor) {
620         try {
621             monitor.beginTask(PatchMessages.PreviewPatchPage_GuessFuzzProgress_text, IProgressMonitor.UNKNOWN);
622             FileDiff[] diffs= getDiffs();
623             if (diffs==null||diffs.length<=0)
624                 return -1;
625             int fuzz= -1;
626             for (int i= 0; i<diffs.length; i++) {
627                 FileDiff d= diffs[i];
628                 IFile file= getTargetFile(d);
629                 if (file != null && file.exists()) {
630                     List lines= load(file, false);
631                     FileDiffResult result = getDiffResult(d);
632                     int f = result.calculateFuzz(lines, monitor);
633                     if (f > fuzz)
634                         fuzz = f;
635                 }
636             }
637             return fuzz;
638         } finally {
639             monitor.done();
640         }
641     }
642     
643     public void refresh() {
644         diffResults.clear();
645         refresh(getDiffs());
646     }
647     
648     protected void refresh(FileDiff[] diffs) {
649         for (int i = 0; i < diffs.length; i++) {
650             FileDiff diff = diffs[i];
651             FileDiffResult result = getDiffResult(diff);
652             ((WorkspaceFileDiffResult)result).refresh();
653         }
654     }
655     
656     public FileDiffResult getDiffResult(FileDiff diff) {
657         FileDiffResult result = (FileDiffResult)diffResults.get(diff);
658         if (result == null) {
659             result = new WorkspaceFileDiffResult(diff, getConfiguration());
660             diffResults.put(diff, result);
661         }
662         return result;
663     }
664
665     public PatchConfiguration getConfiguration() {
666         return configuration;
667     }
668
669     /**
670      * Return the project that contains this diff or <code>null</code>
671      * if the patch is not a workspace patch.
672      * @param diff the diff
673      * @return the project that contains the diff
674      */

675     public DiffProject getProject(FileDiff diff) {
676         return diff.getProject();
677     }
678
679     /*
680      * Returns <code>true</code> if new value differs from old.
681      */

682     public boolean setReversed(boolean reverse) {
683         if (getConfiguration().isReversed() != reverse) {
684             getConfiguration().setReversed(reverse);
685             refresh();
686             return true;
687         }
688         return false;
689     }
690     
691     public boolean isReversed() {
692         return getConfiguration().isReversed();
693     }
694     
695     /**
696      * Cache the contents for the given file diff. These contents
697      * will be used for the diff when the patch is applied. When the
698      * patch is applied, it is assumed that the provided contents
699      * already have all relevant hunks applied.
700      * @param diff the file diff
701      * @param contents the contents for the file diff
702      */

703     public void cacheContents(FileDiff diff, byte[] contents) {
704         contentCache.put(diff, contents);
705     }
706     
707     /**
708      * Return whether contents have been cached for the
709      * given file diff.
710      * @param diff the file diff
711      * @return whether contents have been cached for the file diff
712      * @see #cacheContents(FileDiff, byte[])
713      */

714     public boolean hasCachedContents(FileDiff diff) {
715         return contentCache.containsKey(diff);
716     }
717
718     /**
719      * Return the content lines that are cached for the given
720      * file diff.
721      * @param diff the file diff
722      * @return the content lines that are cached for the file diff
723      */

724     public List getCachedLines(FileDiff diff) {
725         byte[] contents = (byte[])contentCache.get(diff);
726         if (contents != null) {
727             BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(contents)));
728             return readLines(reader);
729         }
730         return null;
731     }
732
733     /**
734      * Return the contents that are cached for the given diff or
735      * <code>null</code> if there is no contents cached.
736      * @param diff the diff
737      * @return the contents that are cached for the given diff or
738      * <code>null</code>
739      */

740     public byte[] getCachedContents(FileDiff diff) {
741         return (byte[])contentCache.get(diff);
742     }
743     
744     /**
745      * Return whether the patcher has any cached contents.
746      * @return whether the patcher has any cached contents
747      */

748     public boolean hasCachedContents() {
749         return !contentCache.isEmpty();
750     }
751
752     /**
753      * Clear any cached contents.
754      */

755     public void clearCachedContents() {
756         contentCache.clear();
757         mergedHunks.clear();
758     }
759     
760     public void setProperty(String JavaDoc key, Object JavaDoc value) {
761         getConfiguration().setProperty(key, value);
762     }
763     
764     public Object JavaDoc getProperty(String JavaDoc key) {
765         return getConfiguration().getProperty(key);
766     }
767
768     public boolean isManuallyMerged(Hunk hunk) {
769         return mergedHunks.contains(hunk);
770     }
771
772     public void setManuallyMerged(Hunk hunk, boolean merged) {
773         if (merged)
774             mergedHunks.add(hunk);
775         else
776             mergedHunks.remove(hunk);
777     }
778
779     public IProject getTargetProject(FileDiff diff) {
780         DiffProject dp = getProject(diff);
781         if (dp != null)
782             return dp.getProject();
783         IResource tr = getTarget();
784         if (tr instanceof IWorkspaceRoot) {
785             IWorkspaceRoot root = (IWorkspaceRoot) tr;
786             return root.getProject(diff.getPath(isReversed()).segment(0));
787         }
788         return tr.getProject();
789     }
790
791     public static Patcher getPatcher(PatchConfiguration configuration) {
792         return (Patcher)configuration.getProperty(PROP_PATCHER);
793     }
794     
795     public boolean hasRejects() {
796         for (Iterator iterator = diffResults.values().iterator(); iterator.hasNext();) {
797             FileDiffResult result = (FileDiffResult) iterator.next();
798             if (result.hasRejects())
799                 return true;
800         }
801         return false;
802     }
803 }
804
Popular Tags