001: /*
002: * CVS.java
003: *
004: * Copyright (C) 1998-2004 Peter Graves
005: * $Id: CVS.java,v 1.5 2004/08/08 00:54:04 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.util.List;
025: import javax.swing.SwingUtilities;
026: import javax.swing.undo.CompoundEdit;
027:
028: public final class CVS implements Constants {
029: public static void cvs() {
030: MessageDialog.showMessageDialog(
031: "The command \"cvs\" requires an argument", "Error");
032: }
033:
034: public static void cvs(String args) {
035: final Editor editor = Editor.currentEditor();
036: final Buffer buffer = editor.getBuffer();
037: if (buffer.getFile() == null)
038: return;
039: buffer.setBusy(true);
040: editor.setWaitCursor();
041: final String name = buffer.getFile().getName();
042: FastStringBuffer sb = new FastStringBuffer("cvs ");
043: sb.append(args);
044: // "cvs -H" doesn't need a filename.
045: if (!args.trim().startsWith("-H ")) {
046: sb.append(' ');
047: if (name.indexOf(' ') >= 0) {
048: // Enclose filename in double quotes since it contains an
049: // embedded space.
050: sb.append('"');
051: sb.append(name);
052: sb.append('"');
053: } else
054: sb.append(name);
055: }
056: final String cmd = sb.toString();
057: Runnable commandRunnable = new Runnable() {
058: public void run() {
059: final String output = command(cmd, buffer
060: .getCurrentDirectory());
061: Runnable completionRunnable = new Runnable() {
062: public void run() {
063: cvsCompleted(editor, buffer, cmd, output);
064: }
065: };
066: SwingUtilities.invokeLater(completionRunnable);
067: }
068: };
069: new Thread(commandRunnable).start();
070: }
071:
072: private static void cvsCompleted(Editor editor, Buffer buffer,
073: String cmd, String output) {
074: if (output != null && output.length() > 0) {
075: Buffer buf;
076: if (cmd.startsWith("cvs diff"))
077: buf = new DiffOutputBuffer(buffer, output, VC_CVS);
078: else
079: buf = OutputBuffer.getOutputBuffer(output);
080: buf.setTitle(cmd);
081: editor.makeNext(buf);
082: editor.activateInOtherWindow(buf);
083: }
084: buffer.checkCVS();
085: buffer.setBusy(false);
086: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
087: Editor ed = it.nextEditor();
088: if (ed.getBuffer() == buffer) {
089: ed.setDefaultCursor();
090: // Update CVS information in status bar.
091: ed.getFrame().repaintStatusBar();
092: }
093: }
094: }
095:
096: public static void add() {
097: final Editor editor = Editor.currentEditor();
098: final Buffer buffer = editor.getBuffer();
099: if (buffer.getFile() == null)
100: return;
101: buffer.setBusy(true);
102: editor.setWaitCursor();
103: final String name = buffer.getFile().getName();
104: FastStringBuffer sb = new FastStringBuffer("cvs add ");
105: if (name.indexOf(' ') >= 0) {
106: // Enclose filename in double quotes since it contains an embedded
107: // space.
108: sb.append('"');
109: sb.append(name);
110: sb.append('"');
111: } else
112: sb.append(name);
113: final String cmd = sb.toString();
114: Runnable commandRunnable = new Runnable() {
115: public void run() {
116: final String output = command(cmd, buffer
117: .getCurrentDirectory());
118: Runnable completionRunnable = new Runnable() {
119: public void run() {
120: addCompleted(editor, buffer, cmd, output);
121: }
122: };
123: SwingUtilities.invokeLater(completionRunnable);
124: }
125: };
126: new Thread(commandRunnable).start();
127: }
128:
129: private static void addCompleted(Editor editor, Buffer buffer,
130: String cmd, String output) {
131: OutputBuffer buf = OutputBuffer.getOutputBuffer(output);
132: buf.setTitle(cmd);
133: editor.makeNext(buf);
134: editor.activateInOtherWindow(buf);
135: buffer.checkCVS();
136: buffer.setBusy(false);
137: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
138: Editor ed = it.nextEditor();
139: if (ed.getBuffer() == buffer) {
140: ed.setDefaultCursor();
141: // Update CVS information in status bar.
142: ed.getFrame().repaintStatusBar();
143: }
144: }
145: }
146:
147: public static void commit() {
148: final Editor editor = Editor.currentEditor();
149: Buffer parentBuffer = editor.getBuffer();
150: if (parentBuffer instanceof DiffOutputBuffer)
151: parentBuffer = parentBuffer.getParentBuffer();
152: if (parentBuffer == null)
153: return;
154: if (parentBuffer.getFile() == null)
155: return;
156: final String title = "cvs commit ".concat(parentBuffer
157: .getFile().getName());
158: boolean save = false;
159: if (parentBuffer.isModified()) {
160: int response = ConfirmDialog
161: .showConfirmDialogWithCancelButton(editor,
162: CHECK_SAVE_PROMPT, title);
163: switch (response) {
164: case RESPONSE_YES:
165: save = true;
166: break;
167: case RESPONSE_NO:
168: break;
169: case RESPONSE_CANCEL:
170: return;
171: }
172: editor.repaintNow();
173: }
174: if (!save || parentBuffer.save()) {
175: // Look for existing checkin buffer before making a new one.
176: CheckinBuffer checkinBuffer = null;
177: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
178: Buffer buf = it.nextBuffer();
179: if (buf instanceof CheckinBuffer) {
180: if (buf.getParentBuffer() == parentBuffer) {
181: checkinBuffer = (CheckinBuffer) buf;
182: break;
183: }
184: }
185: }
186: if (checkinBuffer == null) {
187: checkinBuffer = new CheckinBuffer(parentBuffer, VC_CVS);
188: checkinBuffer.setFormatter(new PlainTextFormatter(
189: checkinBuffer));
190: checkinBuffer.setTitle(title);
191: }
192: editor.makeNext(checkinBuffer);
193: editor.activateInOtherWindow(checkinBuffer);
194: }
195: }
196:
197: public static void diff() {
198: diff(null);
199: }
200:
201: public static void diff(String args) {
202: final Editor editor = Editor.currentEditor();
203: Buffer parentBuffer = editor.getBuffer();
204: if (parentBuffer instanceof CheckinBuffer)
205: parentBuffer = parentBuffer.getParentBuffer();
206: if (parentBuffer.getFile() == null)
207: return;
208: final String name = parentBuffer.getFile().getName();
209: if (args == null)
210: args = "-u";
211: FastStringBuffer sb = new FastStringBuffer("cvs diff ");
212: sb.append(args);
213: sb.append(' ');
214: if (name.indexOf(' ') >= 0) {
215: // Enclose filename in double quotes since it contains an embedded
216: // space.
217: sb.append('"');
218: sb.append(name);
219: sb.append('"');
220: } else
221: sb.append(name);
222: final String cmd = sb.toString();
223: boolean save = false;
224: if (parentBuffer.isModified()) {
225: int response = ConfirmDialog
226: .showConfirmDialogWithCancelButton(editor,
227: CHECK_SAVE_PROMPT, cmd);
228: switch (response) {
229: case RESPONSE_YES:
230: save = true;
231: break;
232: case RESPONSE_NO:
233: break;
234: case RESPONSE_CANCEL:
235: return;
236: }
237: editor.repaintNow();
238: }
239: parentBuffer.setBusy(true);
240: if (!save || parentBuffer.save()) {
241: // Kill existing diff output buffer if any for same parent buffer.
242: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
243: Buffer b = it.nextBuffer();
244: if (b instanceof DiffOutputBuffer) {
245: if (b.getParentBuffer() == parentBuffer) {
246: b.kill();
247: break; // There should be one at most.
248: }
249: }
250: }
251: final Buffer finalParentBuffer = parentBuffer;
252: Runnable commandRunnable = new Runnable() {
253: public void run() {
254: final String output = command(cmd,
255: finalParentBuffer.getCurrentDirectory());
256: Runnable completionRunnable = new Runnable() {
257: public void run() {
258: diffCompleted(editor, finalParentBuffer,
259: cmd, output);
260: }
261: };
262: SwingUtilities.invokeLater(completionRunnable);
263: }
264: };
265: new Thread(commandRunnable).start();
266: }
267: }
268:
269: private static void diffCompleted(Editor editor,
270: Buffer parentBuffer, String cmd, String output) {
271: if (output.length() == 0) {
272: parentBuffer.setBusy(false);
273: MessageDialog.showMessageDialog(editor,
274: "No changes since latest version", parentBuffer
275: .getFile().getName());
276: } else {
277: DiffOutputBuffer buf = new DiffOutputBuffer(parentBuffer,
278: output, VC_CVS);
279: buf.setTitle(cmd);
280: editor.makeNext(buf);
281: editor.activateInOtherWindow(buf);
282: parentBuffer.setBusy(false);
283: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
284: Editor ed = it.nextEditor();
285: if (ed.getBuffer() == parentBuffer)
286: ed.setDefaultCursor();
287: }
288: }
289: }
290:
291: public static void diffDir() {
292: final Editor editor = Editor.currentEditor();
293: final Buffer buffer = editor.getBuffer();
294: final String cmd = "cvs diff -u";
295: final File directory = buffer.getCurrentDirectory();
296: // Kill existing diff output buffer if any for same directory.
297: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
298: Buffer b = it.nextBuffer();
299: if (b instanceof DiffOutputBuffer) {
300: if (directory.equals(((DiffOutputBuffer) b)
301: .getDirectory())) {
302: b.kill();
303: break; // There should be one at most.
304: }
305: }
306: }
307: final DiffOutputBuffer buf = new DiffOutputBuffer(directory,
308: null, VC_CVS);
309: buf.setTitle(cmd);
310: editor.makeNext(buf);
311: Editor ed = editor.activateInOtherWindow(buf);
312: ed.setWaitCursor();
313: buf.setBusy(true);
314: Runnable commandRunnable = new Runnable() {
315: public void run() {
316: final String output = command(cmd, directory);
317: Runnable completionRunnable = new Runnable() {
318: public void run() {
319: diffDirCompleted(buf, output);
320: }
321: };
322: SwingUtilities.invokeLater(completionRunnable);
323: }
324: };
325: new Thread(commandRunnable).start();
326: }
327:
328: private static void diffDirCompleted(Buffer buffer, String output) {
329: buffer.setText(output);
330: buffer.setBusy(false);
331: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
332: Editor ed = it.nextEditor();
333: if (ed.getBuffer() == buffer) {
334: ed.setDot(buffer.getFirstLine(), 0);
335: ed.setTopLine(buffer.getFirstLine());
336: ed.setUpdateFlag(REPAINT);
337: ed.updateDisplay();
338: }
339: }
340: }
341:
342: public static void replaceComment(final Editor editor,
343: final String comment) {
344: if (!(editor.getBuffer() instanceof CheckinBuffer)) {
345: Debug.bug();
346: return;
347: }
348: final CheckinBuffer buffer = (CheckinBuffer) editor.getBuffer();
349: String oldComment = extractComment(buffer);
350: if (oldComment.equals(comment))
351: return;
352: insertComment(editor, comment);
353: }
354:
355: public static String extractComment(final CheckinBuffer buffer) {
356: return buffer.getText();
357: }
358:
359: private static void insertComment(final Editor editor,
360: final String comment) {
361: final CheckinBuffer buffer = (CheckinBuffer) editor.getBuffer();
362: try {
363: buffer.lockWrite();
364: } catch (InterruptedException e) {
365: Log.error(e);
366: return;
367: }
368: try {
369: CompoundEdit compoundEdit = editor.beginCompoundEdit();
370: editor.selectAll();
371: editor.deleteRegion();
372: editor.insertString(comment);
373: editor.endCompoundEdit(compoundEdit);
374: buffer.modified();
375: } finally {
376: buffer.unlockWrite();
377: }
378: final Position end = buffer.getEnd();
379: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
380: Editor ed = it.nextEditor();
381: if (ed.getBuffer() == buffer) {
382: ed.setTopLine(buffer.getFirstLine());
383: ed.setDot(end.copy()); // No undo.
384: ed.moveCaretToDotCol();
385: ed.setUpdateFlag(REPAINT);
386: ed.updateDisplay();
387: }
388: }
389: }
390:
391: public static void finish(final Editor editor,
392: final CheckinBuffer checkinBuffer) {
393: final Buffer parentBuffer = checkinBuffer.getParentBuffer();
394: if (parentBuffer.getFile() == null)
395: return;
396: final String name = parentBuffer.getFile().getName();
397: final File tempFile = Utilities.getTempFile();
398: if (!checkinBuffer.writeFile(tempFile)) {
399: MessageDialog.showMessageDialog(editor,
400: "Unable to write temporary file ".concat(tempFile
401: .canonicalPath()), "Error");
402: return;
403: }
404: FastStringBuffer sb = new FastStringBuffer("cvs commit -F ");
405: // Enclose both filenames in double quotes in case they contain
406: // embedded spaces.
407: sb.append('"');
408: sb.append(tempFile.canonicalPath());
409: sb.append('"');
410: sb.append(' ');
411: sb.append('"');
412: sb.append(name);
413: sb.append('"');
414: final String cmd = sb.toString();
415: editor.setWaitCursor();
416: checkinBuffer.setBusy(true);
417: parentBuffer.setBusy(true);
418: Runnable commandRunnable = new Runnable() {
419: public void run() {
420: final CvsCommand cvsCommand = new CvsCommand(cmd,
421: parentBuffer.getCurrentDirectory());
422: cvsCommand.run();
423: tempFile.delete();
424: Runnable completionRunnable = new Runnable() {
425: public void run() {
426: finishCompleted(editor, checkinBuffer,
427: parentBuffer, cvsCommand, name,
428: tempFile);
429: }
430: };
431: SwingUtilities.invokeLater(completionRunnable);
432: }
433: };
434: new Thread(commandRunnable).start();
435: }
436:
437: private static void finishCompleted(Editor editor,
438: Buffer checkinBuffer, Buffer parentBuffer,
439: CvsCommand cvsCommand, String name, File tempFile) {
440: checkinBuffer.setBusy(false);
441: if (cvsCommand.exitValue() != 0) {
442: // Error.
443: OutputBuffer buf = OutputBuffer.getOutputBuffer(cvsCommand
444: .getOutput());
445: buf.setTitle("cvs commit ".concat(name));
446: editor.makeNext(buf);
447: editor.activate(buf);
448: } else {
449: // Success. Kill old diff buffer, if any; its contents are no
450: // longer correct.
451: for (BufferIterator it = new BufferIterator(); it.hasNext();) {
452: Buffer b = it.nextBuffer();
453: if (b instanceof DiffOutputBuffer) {
454: if (b.getParentBuffer() == parentBuffer) {
455: b.kill();
456: break; // There should be one at most.
457: }
458: }
459: }
460: if (Editor.getBufferList().contains(checkinBuffer))
461: checkinBuffer.kill();
462: if (editor.getOtherEditor() != null) {
463: editor.otherWindow();
464: editor.unsplitWindow();
465: } else
466: editor.updateDisplay();
467: }
468: // The source file may have been modified by the checkin process.
469: editor.reactivate(parentBuffer);
470: parentBuffer.checkCVS();
471: parentBuffer.setBusy(false);
472: for (EditorIterator it = new EditorIterator(); it.hasNext();) {
473: Editor ed = it.nextEditor();
474: if (ed.getBuffer().isBusy())
475: ed.setWaitCursor();
476: else
477: ed.setDefaultCursor();
478: // Update CVS information in status bar.
479: if (ed.getBuffer() == parentBuffer)
480: ed.getFrame().repaintStatusBar();
481: }
482: Editor.restoreFocus();
483: }
484:
485: public static void log() {
486: log("");
487: }
488:
489: public static void log(String args) {
490: boolean useCurrentFile = true;
491: List list = Utilities.tokenize(args);
492: for (int i = 0; i < list.size(); i++) {
493: String arg = (String) list.get(i);
494: if (arg.charAt(0) != '-') {
495: // Must be a filename.
496: useCurrentFile = false;
497: break;
498: }
499: }
500: final Editor editor = Editor.currentEditor();
501: final Buffer parentBuffer = editor.getBuffer();
502: FastStringBuffer sb = new FastStringBuffer("cvs log ");
503: sb.append(args);
504: if (useCurrentFile) {
505: if (parentBuffer.getFile() == null)
506: return;
507: final String name = parentBuffer.getFile().getName();
508: sb.append(' ');
509: if (name.indexOf(' ') >= 0) {
510: // Enclose filename in double quotes since it contains an
511: // embedded space.
512: sb.append('"');
513: sb.append(name);
514: sb.append('"');
515: } else
516: sb.append(name);
517: }
518: final String cmd = sb.toString();
519: editor.setWaitCursor();
520: final String output = command(cmd, parentBuffer
521: .getCurrentDirectory());
522: OutputBuffer buf = OutputBuffer.getOutputBuffer(output);
523: buf.setTitle(cmd);
524: editor.makeNext(buf);
525: editor.activateInOtherWindow(buf);
526: editor.setDefaultCursor();
527: }
528:
529: // Implementation.
530: private static final String command(String cmd,
531: File workingDirectory) {
532: CvsCommand cvsCommand = new CvsCommand(cmd, workingDirectory);
533: cvsCommand.run();
534: return cvsCommand.getOutput();
535: }
536:
537: private static final class CvsCommand {
538: final private String cmd;
539: final private File workingDirectory;
540: private ShellCommand shellCommand;
541:
542: public CvsCommand(String cmd, File workingDirectory) {
543: this .cmd = cmd;
544: this .workingDirectory = workingDirectory;
545: }
546:
547: public void run() {
548: shellCommand = new ShellCommand(cmd, workingDirectory);
549: shellCommand.run();
550: }
551:
552: public final String getOutput() {
553: Debug.assertTrue(shellCommand != null);
554: return shellCommand.getOutput();
555: }
556:
557: public final int exitValue() {
558: Debug.assertTrue(shellCommand != null);
559: return shellCommand.exitValue();
560: }
561: }
562: }
|