001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012:
013: package org.tmatesoft.svn.cli.command;
014:
015: import java.io.File;
016: import java.io.InputStream;
017: import java.io.PrintStream;
018:
019: import org.tmatesoft.svn.cli.SVNArgument;
020: import org.tmatesoft.svn.cli.SVNCommand;
021: import org.tmatesoft.svn.core.SVNException;
022: import org.tmatesoft.svn.core.SVNURL;
023: import org.tmatesoft.svn.core.internal.util.SVNFormatUtil;
024: import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
025: import org.tmatesoft.svn.core.wc.DefaultSVNDiffGenerator;
026: import org.tmatesoft.svn.core.wc.ISVNDiffGenerator;
027: import org.tmatesoft.svn.core.wc.ISVNDiffStatusHandler;
028: import org.tmatesoft.svn.core.wc.SVNDiffClient;
029: import org.tmatesoft.svn.core.wc.SVNDiffOptions;
030: import org.tmatesoft.svn.core.wc.SVNDiffStatus;
031: import org.tmatesoft.svn.core.wc.SVNRevision;
032: import org.tmatesoft.svn.core.wc.SVNStatusType;
033:
034: /**
035: * @version 1.1.1
036: * @author TMate Software Ltd.
037: */
038: public class SVNDiffCommand extends SVNCommand implements
039: ISVNDiffStatusHandler {
040:
041: private PrintStream myOut;
042:
043: public void run(InputStream in, PrintStream out, PrintStream err)
044: throws SVNException {
045: run(out, err);
046: }
047:
048: public void run(final PrintStream out, PrintStream err)
049: throws SVNException {
050: myOut = out;
051: boolean error = false;
052: SVNDiffClient differ = getClientManager().getDiffClient();
053: if (getCommandLine().hasArgument(SVNArgument.EXTENSIONS)) {
054: SVNDiffOptions diffOptions = new SVNDiffOptions(
055: getCommandLine().hasArgument(
056: SVNArgument.IGNORE_ALL_WS),
057: getCommandLine().hasArgument(
058: SVNArgument.IGNORE_WS_CHANGE),
059: getCommandLine().hasArgument(
060: SVNArgument.IGNORE_EOL_STYLE));
061: ISVNDiffGenerator generator = differ.getDiffGenerator();
062: if (generator instanceof DefaultSVNDiffGenerator) {
063: ((DefaultSVNDiffGenerator) generator)
064: .setDiffOptions(diffOptions);
065: }
066: }
067: File userDir = new File(".").getAbsoluteFile().getParentFile();
068: differ.getDiffGenerator().setBasePath(userDir);
069:
070: boolean useAncestry = getCommandLine().hasArgument(
071: SVNArgument.USE_ANCESTRY);
072: boolean recursive = !getCommandLine().hasArgument(
073: SVNArgument.NON_RECURSIVE);
074: boolean summarize = getCommandLine().hasArgument(
075: SVNArgument.SUMMARIZE);
076:
077: differ.getDiffGenerator().setDiffDeleted(
078: !getCommandLine().hasArgument(
079: SVNArgument.NO_DIFF_DELETED));
080: differ.getDiffGenerator().setForcedBinaryDiff(
081: getCommandLine().hasArgument(SVNArgument.FORCE));
082:
083: if (getCommandLine().getURLCount() == 2
084: && !getCommandLine().hasPaths()) {
085: // diff url1[@r] url2[@r] (case 3)
086: SVNURL url1 = SVNURL.parseURIEncoded(getCommandLine()
087: .getURL(0));
088: SVNURL url2 = SVNURL.parseURIEncoded(getCommandLine()
089: .getURL(1));
090: SVNRevision peg1 = getCommandLine().getPegRevision(0);
091: SVNRevision peg2 = getCommandLine().getPegRevision(1);
092: if (peg1 == SVNRevision.UNDEFINED) {
093: peg1 = SVNRevision.HEAD;
094: }
095: if (peg2 == SVNRevision.UNDEFINED) {
096: peg2 = SVNRevision.HEAD;
097: }
098:
099: if (summarize) {
100: differ.doDiffStatus(url1, peg1, url2, peg2, recursive,
101: useAncestry, this );
102: } else {
103: differ.doDiff(url1, peg1, url2, peg2, recursive,
104: useAncestry, out);
105: }
106: } else {
107: SVNRevision rN = SVNRevision.UNDEFINED;
108: SVNRevision rM = SVNRevision.UNDEFINED;
109: String revStr = (String) getCommandLine().getArgumentValue(
110: SVNArgument.REVISION);
111:
112: if (revStr != null) {
113: SVNRevision[] revRange = getStartEndRevisions();
114: rN = revRange[0];
115: rM = revRange[1];
116: } else if (revStr == null
117: && getCommandLine().hasArgument(SVNArgument.CHANGE)) {
118: long changeRev = Long
119: .parseLong((String) getCommandLine()
120: .getArgumentValue(SVNArgument.CHANGE));
121: if (changeRev >= 0) {
122: rM = SVNRevision.create(changeRev);
123: rN = SVNRevision.create(changeRev - 1);
124: } else {
125: rN = SVNRevision.create(-changeRev);
126: rM = SVNRevision.create((-changeRev) - 1);
127: }
128: }
129:
130: if (getCommandLine().hasArgument(SVNArgument.OLD)) {
131: // diff [-rN[:M]] --old=url[@r] [--new=url[@r]] [path...] (case2)
132: String oldPath = (String) getCommandLine()
133: .getArgumentValue(SVNArgument.OLD);
134: String newPath = (String) getCommandLine()
135: .getArgumentValue(SVNArgument.NEW);
136: if (newPath == null) {
137: newPath = oldPath;
138: }
139: if (oldPath.startsWith("=")) {
140: oldPath = oldPath.substring(1);
141: }
142: if (newPath.startsWith("=")) {
143: newPath = newPath.substring(1);
144: }
145: if (oldPath.indexOf('@') > 0) {
146: rN = SVNRevision.parse(oldPath.substring(oldPath
147: .lastIndexOf('@') + 1));
148: oldPath = oldPath.substring(0, oldPath
149: .lastIndexOf('@'));
150: }
151: if (newPath.indexOf('@') > 0) {
152: rM = SVNRevision.parse(newPath.substring(newPath
153: .lastIndexOf('@') + 1));
154: newPath = newPath.substring(0, newPath
155: .lastIndexOf('@'));
156: }
157: if (getCommandLine().getPathCount() == 0) {
158: getCommandLine().setPathAt(0, "");
159: }
160: if (rN == SVNRevision.UNDEFINED) {
161: rN = getCommandLine().isURL(oldPath) ? SVNRevision.HEAD
162: : SVNRevision.BASE;
163: }
164: if (rM == SVNRevision.UNDEFINED) {
165: rM = getCommandLine().isURL(newPath) ? SVNRevision.HEAD
166: : SVNRevision.WORKING;
167: }
168:
169: for (int i = 0; i < getCommandLine().getPathCount(); i++) {
170: String p = getCommandLine().getPathAt(i);
171: p = p.replace(File.separatorChar, '/');
172: if (".".equals(p)) {
173: p = "";
174: }
175: String oP = SVNPathUtil.append(oldPath, p);
176: String nP = SVNPathUtil.append(newPath, p);
177: try {
178: if (!getCommandLine().isURL(oP)
179: && getCommandLine().isURL(nP)) {
180: File path1 = new File(oP).getAbsoluteFile();
181: SVNURL url2 = SVNURL.parseURIEncoded(nP);
182: // path:url
183: if (summarize) {
184: differ.doDiffStatus(path1, rN, url2,
185: rM, recursive, useAncestry,
186: this );
187: } else {
188: differ.doDiff(path1, rN, url2, rM,
189: recursive, useAncestry, out);
190: }
191: } else if (getCommandLine().isURL(oP)
192: && !getCommandLine().isURL(nP)) {
193: // url:path
194: File path2 = new File(nP).getAbsoluteFile();
195: SVNURL url1 = SVNURL.parseURIEncoded(oP);
196: if (summarize) {
197: differ.doDiffStatus(url1, rN, path2,
198: rM, recursive, useAncestry,
199: this );
200: } else {
201: differ.doDiff(url1, rN, path2, rM,
202: recursive, useAncestry, out);
203: }
204: } else if (getCommandLine().isURL(oP)
205: && getCommandLine().isURL(nP)) {
206: // url:url
207: SVNURL url1 = SVNURL.parseURIEncoded(oP);
208: SVNURL url2 = SVNURL.parseURIEncoded(nP);
209: if (summarize) {
210: differ.doDiffStatus(url1, rN, url2, rM,
211: recursive, useAncestry, this );
212: } else {
213: differ.doDiff(url1, rN, url2, rM,
214: recursive, useAncestry, out);
215: }
216: } else {
217: // path:path
218: File path1 = new File(oP).getAbsoluteFile();
219: File path2 = new File(nP).getAbsoluteFile();
220: if (summarize) {
221: differ.doDiffStatus(path1, rN, path2,
222: rM, recursive, useAncestry,
223: this );
224: } else {
225: differ.doDiff(path1, rN, path2, rM,
226: recursive, useAncestry, out);
227: }
228: }
229: } catch (SVNException e) {
230: differ.getDebugLog().info(e);
231: error = true;
232: println(err, e.getMessage());
233: }
234: }
235: } else {
236: // diff [-rN[:M]] target[@r] [...] (case1)
237: SVNRevision r1 = rN;
238: SVNRevision r2 = rM;
239: r1 = r1 == SVNRevision.UNDEFINED ? SVNRevision.BASE
240: : r1;
241: r2 = r2 == SVNRevision.UNDEFINED ? SVNRevision.WORKING
242: : r2;
243: boolean peggedDiff = (r1 != SVNRevision.WORKING
244: && r1 != SVNRevision.BASE && r1 != SVNRevision.PREVIOUS)
245: || (r2 != SVNRevision.WORKING
246: && r2 != SVNRevision.BASE && r2 != SVNRevision.PREVIOUS);
247: peggedDiff &= !summarize;
248:
249: for (int i = 0; i < getCommandLine().getPathCount(); i++) {
250: String path = getCommandLine().getPathAt(i);
251: File path1 = new File(path).getAbsoluteFile();
252: if (peggedDiff) {
253: SVNRevision peg = getCommandLine()
254: .getPathPegRevision(i);
255: peg = peg == SVNRevision.UNDEFINED ? SVNRevision.WORKING
256: : peg;
257: differ.doDiff(path1, peg, r1, r2, recursive,
258: useAncestry, out);
259: } else {
260: if (summarize) {
261: differ.doDiffStatus(path1, r1, path1, r2,
262: recursive, useAncestry, this );
263: } else {
264: differ.doDiff(path1, r1, path1, r2,
265: recursive, useAncestry, out);
266: }
267: }
268: }
269: r1 = rN;
270: r2 = rM;
271: peggedDiff = r1 != SVNRevision.WORKING
272: && r1 != SVNRevision.BASE;
273: peggedDiff &= !summarize;
274: r2 = r2 == SVNRevision.UNDEFINED ? SVNRevision.HEAD
275: : r2;
276:
277: for (int i = 0; i < getCommandLine().getURLCount(); i++) {
278: String url = getCommandLine().getURL(i);
279: SVNURL url1 = SVNURL.parseURIEncoded(url);
280: if (peggedDiff) {
281: SVNRevision peg = getCommandLine()
282: .getPegRevision(i);
283: peg = peg == SVNRevision.UNDEFINED ? SVNRevision.HEAD
284: : peg;
285: differ.doDiff(url1, peg, r1, r2, recursive,
286: useAncestry, out);
287: } else {
288: if (summarize) {
289: differ.doDiffStatus(url1, r1, url1, r2,
290: recursive, useAncestry, this );
291: } else {
292: differ.doDiff(url1, r1, url1, r2,
293: recursive, useAncestry, out);
294: }
295: }
296: }
297: }
298: }
299: out.flush();
300: if (error) {
301: System.exit(1);
302: }
303: }
304:
305: public void handleDiffStatus(SVNDiffStatus diffStatus)
306: throws SVNException {
307: if (diffStatus.getModificationType() == SVNStatusType.STATUS_NONE
308: && !diffStatus.isPropertiesModified()) {
309: return;
310: }
311: StringBuffer result = new StringBuffer();
312: result.append(diffStatus.getModificationType().getCode());
313: result.append(diffStatus.isPropertiesModified() ? 'M' : ' ');
314: result.append(" ");
315: if (diffStatus.getFile() != null) {
316: result.append(SVNFormatUtil
317: .formatPath(diffStatus.getFile()));
318: } else {
319: result.append(diffStatus.getPath());
320: }
321: myOut.println(result.toString());
322: }
323: }
|