001: package tide.exttools.SVN;
002:
003: import snow.utils.gui.Icons;
004: import snow.texteditor.SimpleDocument;
005: import java.awt.event.*;
006: import tide.sources.SourceFile;
007: import javax.swing.*;
008: import snow.utils.storage.FileUtils;
009: import java.util.*;
010: import snow.utils.ProcessUtils;
011: import snow.utils.SysUtils;
012: import tide.editor.MainEditorFrame;
013: import java.io.*;
014: import tide.project.ProjectSettings;
015:
016: /**
017: * Todo: support comments... (write them, show them...) (maybe when shift pressed ?)
018: * TODO: http://www.ibm.com/developerworks/java/library/j-svnbins.html
019: *
020: */
021: public final class SVNOps {
022: private SVNOps() {
023: }
024:
025: static void addCredentialsIfAny(List<String> args) {
026: ProjectSettings actualProject = MainEditorFrame.instance
027: .getActualProject();
028: String user = actualProject.getProperty("Subversion_username",
029: "");
030: if (user.length() < 0) {
031: args.add("--username");
032: args.add(user);
033: }
034: String pass = actualProject.getProperty("Subversion_password",
035: "");
036: if (pass.length() < 0) {
037: args.add("--password");
038: args.add(pass);
039: }
040: }
041:
042: static void addRecurse(File fileOrFolder) throws Exception {
043:
044: SimpleDocument doc = MainEditorFrame.instance.outputPanels
045: .selectToolsTab(false).doc;
046:
047: // all adds must be made, for all folders
048: if (fileOrFolder.isDirectory()) {
049: doc.appendLine("SVN add (recurse) "
050: + fileOrFolder.getName() + ":");
051:
052: // recurse
053: List<File> recFolders = new ArrayList<File>();
054: FileUtils.getFoldersRecurse(fileOrFolder, recFolders, true); // ignore names stating with "."
055: for (File fi : recFolders) {
056: String rep = addNotRecurse(fi).trim();
057: if (rep.length() > 0) {
058: doc.appendLine(rep);
059: }
060: }
061: } else {
062: String rep = addNotRecurse(fileOrFolder);
063: doc.appendLine("SVN add " + fileOrFolder.getName() + ":\n"
064: + rep);
065: }
066: }
067:
068: /*
069: -q [--quiet] : print as little as possible
070: -N [--non-recursive] : operate on single directory only
071: --targets arg : pass contents of file ARG as additional args
072: --no-unlock : don't unlock the targets
073: -m [--message] arg : specify log message ARG
074: -F [--file] arg : read log message from file ARG
075: --force-log : force validity of log message source
076: --editor-cmd arg : use ARG as external editor
077: --encoding arg : treat value as being in charset encoding ARG
078: --username arg : specify a username ARG
079: --password arg : specify a password ARG
080: --no-auth-cache : do not cache authentication tokens
081: --non-interactive : do no interactive prompting
082: --config-dir arg : read user configuration files from directory ARG
083: */
084: /** Calls add and commit
085: * seems that add must be called on each directory, it doesn't recurse itself
086: */
087: static void commit(File fileOrFolder, String commitComment)
088: throws Exception {
089: if (commitComment == null) {
090: commitComment = JOptionPane
091: .showInputDialog("Please enter a comment for the SVN commit:");
092: }
093:
094: // all commits are performed
095: ProjectSettings actualProject = MainEditorFrame.instance
096: .getActualProject();
097: File srcHome = actualProject.getSources_Home();
098: String srcHomeName = FileUtils.getCanonicalName(srcHome);
099: String relName = FileUtils.getCanonicalName(fileOrFolder)
100: .substring(srcHomeName.length());
101:
102: List<String> args = new ArrayList<String>();
103: args.add("" + getSVNTool("svn"));
104: args.add("commit");
105: args.add(relName); // no need to *.* here
106: args.add("-m"); // mandatory
107: args.add("\"" + commitComment + "\"");
108: args.add("--no-unlock"); // important to work like in source safe.
109: args.add("--non-interactive");
110: addCredentialsIfAny(args);
111:
112: //ProcessBuilder pb = new ProcessBuilder(args);
113: // important
114: //pb.directory(srcHome);
115:
116: //Process proc = pb.start();
117: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
118: 15 * 1000);
119:
120: SimpleDocument doc = MainEditorFrame.instance.outputPanels
121: .selectToolsTab(true).doc;
122: doc.appendLine("SVN commit " + relName + ":\n" + rep);
123: }
124:
125: static void status(File fileOrFolder, boolean verbose)
126: throws Exception {
127: ProjectSettings actualProject = MainEditorFrame.instance
128: .getActualProject();
129: File srcHome = actualProject.getSources_Home();
130: String srcHomeName = FileUtils.getCanonicalName(srcHome);
131: String relName = FileUtils.getCanonicalName(fileOrFolder)
132: .substring(srcHomeName.length());
133:
134: List<String> args = new ArrayList<String>();
135: args.add("" + getSVNTool("svn"));
136: args.add("status");
137: args.add(relName); // no need to *.* here (and maybe empty)
138:
139: if (verbose) {
140: args.add("--verbose"); // show a lot of infos
141: } else {
142: args.add("-q"); // quiet => don't show the "?" items that are not under version control.
143: }
144: addCredentialsIfAny(args);
145:
146: //ProcessBuilder pb = new ProcessBuilder(args);
147: // important
148: // pb.directory(srcHome);
149:
150: //Process proc = pb.start();
151: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
152: 15 * 1000);
153:
154: SimpleDocument doc = MainEditorFrame.instance.outputPanels
155: .selectToolsTab(true).doc;
156: doc.appendLine("SVN status " + relName + ":\n" + rep);
157: }
158:
159: static void log(File fileOrFolder, boolean verbose)
160: throws Exception {
161: ProjectSettings actualProject = MainEditorFrame.instance
162: .getActualProject();
163: File srcHome = actualProject.getSources_Home();
164: String srcHomeName = FileUtils.getCanonicalName(srcHome);
165: String relName = FileUtils.getCanonicalName(fileOrFolder)
166: .substring(srcHomeName.length());
167:
168: List<String> args = new ArrayList<String>();
169: args.add("" + getSVNTool("svn"));
170: args.add("log");
171: args.add(relName); // no need to *.* here (and maybe empty)
172: if (verbose) {
173: args.add("--verbose");
174: } // show a lot of infos
175: addCredentialsIfAny(args);
176:
177: //ProcessBuilder pb = new ProcessBuilder(args);
178: // important
179: //pb.directory(srcHome);
180:
181: //Process proc = pb.start();
182: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
183: 15 * 1000);
184:
185: SimpleDocument doc = MainEditorFrame.instance.outputPanels
186: .selectToolsTab(true).doc;
187: doc.appendLine("SVN log " + relName + ":\n" + rep);
188: }
189:
190: /**
191: info: Display information about a local or remote item.
192: usage: info [TARGET[@REV]...]
193:
194: Print information about each TARGET (default: '.')
195: TARGET may be either a working-copy path or URL. If specified, REV
196: determines in which revision the target is first looked up.
197:
198: Valid options:
199: -r [--revision] arg : ARG (some commands also take ARG1:ARG2 range)
200: A revision argument can be one of:
201: NUMBER revision number
202: '{' DATE '}' revision at start of the date
203: 'HEAD' latest in repository
204: 'BASE' base rev of item's working copy
205: 'COMMITTED' last commit at or before BASE
206: 'PREV' revision just before COMMITTED
207: -R [--recursive] : descend recursively
208: --targets arg : pass contents of file ARG as additional args
209: --incremental : give output suitable for concatenation
210: --xml : output in XML
211: --username arg : specify a username ARG
212: --password arg : specify a password ARG
213: --no-auth-cache : do not cache authentication tokens
214: --non-interactive : do no interactive prompting
215: --config-dir arg : read user configuration files from directory ARG
216: */
217: static void info(File fileOrFolder) throws Exception {
218: ProjectSettings actualProject = MainEditorFrame.instance
219: .getActualProject();
220: File srcHome = actualProject.getSources_Home();
221: String srcHomeName = FileUtils.getCanonicalName(srcHome);
222: String relName = FileUtils.getCanonicalName(fileOrFolder)
223: .substring(srcHomeName.length());
224:
225: List<String> args = new ArrayList<String>();
226: args.add("" + getSVNTool("svn"));
227: args.add("info");
228: args.add(relName); // no need to *.* here (and maybe empty)
229: addCredentialsIfAny(args);
230:
231: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
232: 15 * 1000);
233:
234: SimpleDocument doc = MainEditorFrame.instance.outputPanels
235: .selectToolsTab(true).doc;
236: doc.appendLine("SVN info " + relName + ":\n" + rep);
237: }
238:
239: /** (Automatically recurse if directory given)
240: * revert: Restore pristine working copy file (undo most local edits).
241: usage: revert PATH...
242:
243: Note: this subcommand does not require network access, and resolves
244: any conflicted states. However, it does not restore removed directories.
245:
246: Valid options:
247: --targets arg : pass contents of file ARG as additional args
248: -R [--recursive] : descend recursively
249: -q [--quiet] : print as little as possible
250: --config-dir arg : read user configuration files from directory ARG
251: */
252: static void revert(File file) throws Exception {
253: ProjectSettings actualProject = MainEditorFrame.instance
254: .getActualProject();
255: File srcHome = actualProject.getSources_Home();
256: String srcHomeName = FileUtils.getCanonicalName(srcHome);
257: String relName = FileUtils.getCanonicalName(file).substring(
258: srcHomeName.length());
259:
260: List<String> args = new ArrayList<String>();
261: args.add("" + getSVNTool("svn"));
262: args.add("revert");
263: args.add(relName);
264: addCredentialsIfAny(args);
265: if (file.isDirectory()) {
266: args.add("--recursive");
267: }
268:
269: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
270: 15 * 1000);
271:
272: SimpleDocument doc = MainEditorFrame.instance.outputPanels
273: .selectToolsTab(true).doc;
274: doc.appendLine("SVN revert " + relName + ":\n" + rep);
275: }
276:
277: /**
278: lock: Lock working copy paths or URLs in the repository, so that
279: no other user can commit changes to them.
280: usage: lock TARGET...
281:
282: Use --force to steal the lock from another user or working copy.
283:
284: Valid options:
285: --targets arg : pass contents of file ARG as additional args
286: -m [--message] arg : specify lock comment ARG
287: -F [--file] arg : read lock comment from file ARG
288: --force-log : force validity of log message source
289: --encoding arg : treat value as being in charset encoding ARG
290: --username arg : specify a username ARG
291: --password arg : specify a password ARG
292: --no-auth-cache : do not cache authentication tokens
293: --non-interactive : do no interactive prompting
294: --config-dir arg : read user configuration files from directory ARG
295: --force : force operation to run
296: */
297: static void lock(File file, boolean enforce, String message)
298: throws Exception {
299: ProjectSettings actualProject = MainEditorFrame.instance
300: .getActualProject();
301: File srcHome = actualProject.getSources_Home();
302: String srcHomeName = FileUtils.getCanonicalName(srcHome);
303: String relName = FileUtils.getCanonicalName(file).substring(
304: srcHomeName.length());
305:
306: List<String> args = new ArrayList<String>();
307: args.add("" + getSVNTool("svn"));
308: args.add("lock");
309: args.add(relName);
310: addCredentialsIfAny(args);
311: args.add("--non-interactive");
312: if (enforce) {
313: args.add("--force");
314: }
315: if (message != null) {
316: args.add("-m");
317: args.add("\"" + message + "\"");
318: }
319:
320: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
321: 15 * 1000);
322:
323: SimpleDocument doc = MainEditorFrame.instance.outputPanels
324: .selectToolsTab(true).doc;
325: doc.appendLine("SVN lock " + relName + ":\n" + rep);
326: }
327:
328: /**
329: unlock: Unlock working copy paths or URLs.
330: usage: unlock TARGET...
331:
332: Use --force to break the lock.
333:
334: Valid options:
335: --targets arg : pass contents of file ARG as additional args
336: --username arg : specify a username ARG
337: --password arg : specify a password ARG
338: --no-auth-cache : do not cache authentication tokens
339: --non-interactive : do no interactive prompting
340: --config-dir arg : read user configuration files from directory ARG
341: --force : force operation to run
342: */
343: static void unlock(File file, boolean enforce) throws Exception {
344: ProjectSettings actualProject = MainEditorFrame.instance
345: .getActualProject();
346: File srcHome = actualProject.getSources_Home();
347: String srcHomeName = FileUtils.getCanonicalName(srcHome);
348: String relName = FileUtils.getCanonicalName(file).substring(
349: srcHomeName.length());
350:
351: List<String> args = new ArrayList<String>();
352: args.add("" + getSVNTool("svn"));
353: args.add("unlock");
354: args.add(relName);
355: addCredentialsIfAny(args);
356: args.add("--non-interactive");
357: if (enforce) {
358: args.add("--force");
359: }
360:
361: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
362: 15 * 1000);
363:
364: SimpleDocument doc = MainEditorFrame.instance.outputPanels
365: .selectToolsTab(true).doc;
366: doc.appendLine("SVN unlock " + relName + ":\n" + rep);
367: }
368:
369: /** it searches your working copy and runs any leftover logs, removing working copy locks in the process.
370: * If Subversion ever tells you that some part of your working copy is “locked”, then this is the command that you should run.
371: */
372: static void cleanup(File fileOrFolder) throws Exception {
373: ProjectSettings actualProject = MainEditorFrame.instance
374: .getActualProject();
375: File srcHome = actualProject.getSources_Home();
376: String srcHomeName = FileUtils.getCanonicalName(srcHome);
377: String relName = FileUtils.getCanonicalName(fileOrFolder)
378: .substring(srcHomeName.length());
379:
380: List<String> args = new ArrayList<String>();
381: args.add("" + getSVNTool("svn"));
382: args.add("cleanup");
383: args.add(relName); // no need to *.* here (and maybe empty)
384: addCredentialsIfAny(args);
385:
386: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
387: 15 * 1000);
388:
389: SimpleDocument doc = MainEditorFrame.instance.outputPanels
390: .selectToolsTab(true).doc;
391: doc.appendLine("SVN cleanup " + relName + ":\n" + rep);
392: }
393:
394: /** update=> recovers deleted, changed files.
395: */
396: static void update(File fileOrFolder) throws Exception {
397: ProjectSettings actualProject = MainEditorFrame.instance
398: .getActualProject();
399: File srcHome = actualProject.getSources_Home();
400: String srcHomeName = FileUtils.getCanonicalName(srcHome);
401: String relName = FileUtils.getCanonicalName(fileOrFolder)
402: .substring(srcHomeName.length());
403:
404: List<String> args = new ArrayList<String>();
405: args.add("" + getSVNTool("svn"));
406: args.add("update");
407: args.add(relName); // no need to *.* here
408: addCredentialsIfAny(args);
409:
410: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
411: 15 * 1000);
412:
413: SimpleDocument doc = MainEditorFrame.instance.outputPanels
414: .selectToolsTab(true).doc;
415: doc.appendLine("SVN update " + relName + ":\n" + rep);
416: }
417:
418: /** Seems that add must be called on each directory, it doesn't recurse itself
419: * MUST BE COMMITED
420: */
421: static String addNotRecurse(File fileOrFolder) throws Exception {
422: ProjectSettings actualProject = MainEditorFrame.instance
423: .getActualProject();
424: File srcHome = actualProject.getSources_Home();
425: String srcHomeName = FileUtils.getCanonicalName(srcHome);
426: String relName = FileUtils.getCanonicalName(fileOrFolder)
427: .substring(srcHomeName.length());
428: if (fileOrFolder.isDirectory()) {
429: // the / is already present
430: relName += "*.*";
431: }
432:
433: List<String> args = new ArrayList<String>();
434: args.add("" + getSVNTool("svn"));
435: args.add("add");
436: args.add(relName);
437: args.add("-q"); // quiet, otherwise, says warnings for all folder already in repository
438: addCredentialsIfAny(args);
439:
440: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
441: 15 * 1000);
442:
443: return rep;
444: }
445:
446: /** ?? Seems that add must be called on each directory, it doesn't recurse itself
447: * MUST BE COMMITED to be deleted on server but this already deletes the local copy
448: */
449: static void delete(File fileOrFolder) throws Exception {
450: ProjectSettings actualProject = MainEditorFrame.instance
451: .getActualProject();
452: File srcHome = actualProject.getSources_Home();
453: String srcHomeName = FileUtils.getCanonicalName(srcHome);
454: String relName = FileUtils.getCanonicalName(fileOrFolder)
455: .substring(srcHomeName.length());
456: if (fileOrFolder.isDirectory()) {
457: // the / is already present
458: relName += "*.*";
459: }
460:
461: List<String> args = new ArrayList<String>();
462: args.add("" + getSVNTool("svn"));
463: args.add("delete");
464: args.add(relName);
465: addCredentialsIfAny(args);
466:
467: String rep = ProcessUtils.readWholeProcessStack(args, srcHome,
468: 15 * 1000);
469:
470: SimpleDocument doc = MainEditorFrame.instance.outputPanels
471: .selectToolsTab(true).doc;
472: doc.appendLine("SVN delete " + relName + ":\n" + rep);
473: }
474:
475: public static File getSVNTool(String name) {
476: ProjectSettings actualProject = MainEditorFrame.instance
477: .getActualProject();
478: if (SysUtils.is_Windows_OS()) {
479: return new File(actualProject.getProperty(
480: "Subversion_path",
481: SVNSettingsDialog.defaultSVNLocation), "bin/"
482: + name + ".exe");
483: } else {
484: // linux, mac ?
485: return new File(actualProject.getProperty(
486: "Subversion_path",
487: SVNSettingsDialog.defaultSVNLocation), "bin/"
488: + name);
489: }
490: }
491:
492: /** Paths must exist and be non empty !
493: */
494: public static boolean isConfigured() {
495: ProjectSettings actualProject = MainEditorFrame.instance
496: .getActualProject();
497: if (actualProject.getProperty("Subversion_repositoryPath", "")
498: .trim().length() == 0)
499: return false;
500:
501: return new File(actualProject.getProperty("Subversion_path",
502: SVNSettingsDialog.defaultSVNLocation)).exists();
503: }
504:
505: /** Must be called prior to operations performing changes (update, delete, lock, ...)
506: */
507: private static void saveFilesAndEmptyCaches(SourceFile sf) {
508: MainEditorFrame.instance.editorPanel.saveChangedFiles();
509: MainEditorFrame.instance.sourcesTreePanel.getTreeModel()
510: .deleteCachedEditedContents(sf);
511: }
512:
513: /** Must be called after having performed changes (update, delete, lock, ...)
514: */
515: private static void refreshFilesFromFileSystem(SourceFile sf) {
516: // this updates the tree
517: MainEditorFrame.instance.sourcesTreePanel.getTreeModel()
518: .scanForDifferencesWithFileSystem(sf);
519: MainEditorFrame.instance.editorPanel
520: .replaceContentWithContentOnDisk();
521: MainEditorFrame.instance.sourcesTreePanel.updateTree();
522: }
523:
524: public static JMenu create_SourcesTreePopupMenu(final SourceFile sf) {
525: JMenu m = new JMenu("Version management (SVN)");
526: m
527: .setToolTipText("Tip: press Ctrl to see only the SVN popup menu");
528:
529: if (!isConfigured()) {
530: m.add("SVN is not configured. (See Ext Tools)");
531: m
532: .add("<html><b>Remark:</b> CSS, VCS, CVN, Mercurial can also be run from outside."
533: + "<br>For example with Tortoise SVN.<br>Just use tIDE's rescan menuitem <b>(F5)</b>.");
534: return m;
535: }
536:
537: // the basic operations are
538: // 1) add/commit
539: // 2) update
540:
541: JMenuItem addCommit = new JMenuItem(
542: "add & commit (sends new data to server)",
543: Icons.sharedRightArrow);
544: addCommit.setToolTipText("Hold Shift to use an empty comment");
545: m.add(addCommit);
546: addCommit.addActionListener(new ActionListener() {
547: public void actionPerformed(ActionEvent ae) {
548: try {
549: String comment = null;
550: int isS = ae.getModifiers() & ae.SHIFT_MASK;
551: if (isS == ae.SHIFT_MASK)
552: comment = "";
553:
554: saveFilesAndEmptyCaches(sf);
555: addRecurse(sf.getFileOrDirectory());
556:
557: commit(sf.getFileOrDirectory(), comment); // null => ask for comment
558: } catch (Exception e) {
559: JOptionPane.showMessageDialog(
560: MainEditorFrame.instance, ""
561: + e.getMessage(),
562: "SVN add/commit error",
563: JOptionPane.ERROR_MESSAGE);
564: }
565: }
566: });
567:
568: JMenuItem update = new JMenuItem(
569: "update (reads the new data from server)",
570: Icons.sharedDownArrow);
571: m.add(update);
572: update.addActionListener(new ActionListener() {
573: public void actionPerformed(ActionEvent ae) {
574: try {
575: saveFilesAndEmptyCaches(sf);
576: update(sf.getFileOrDirectory());
577: refreshFilesFromFileSystem(sf);
578: } catch (Exception e) {
579: JOptionPane.showMessageDialog(
580: MainEditorFrame.instance, ""
581: + e.getMessage(),
582: "SVN update error",
583: JOptionPane.ERROR_MESSAGE);
584: }
585: }
586: });
587:
588: m.addSeparator();
589:
590: // Lock/unlock allow to work like "SourceSafe".
591: // one has to set recursively "svn:needs-lock" on a branch to enforce working with locks.
592: //
593: JMenuItem lock = new JMenuItem(
594: "get lock (disallow other editors)",
595: Icons.sharedClosedLock);
596: m.add(lock);
597: lock.addActionListener(new ActionListener() {
598: public void actionPerformed(ActionEvent ae) {
599: try {
600: String comment = null;
601: int isS = ae.getModifiers() & ae.SHIFT_MASK;
602: if (isS != ae.SHIFT_MASK) {
603: comment = JOptionPane
604: .showInputDialog("Enter a message describing the locking reason");
605: }
606:
607: saveFilesAndEmptyCaches(sf);
608: lock(sf.getFileOrDirectory(), false, comment);
609: refreshFilesFromFileSystem(sf);
610: } catch (Exception e) {
611: JOptionPane.showMessageDialog(
612: MainEditorFrame.instance, ""
613: + e.getMessage(), "SVN lock error",
614: JOptionPane.ERROR_MESSAGE);
615: }
616: }
617: });
618:
619: JMenuItem unlock = new JMenuItem("unlock", Icons.sharedOpenLock);
620: m.add(unlock);
621: unlock.addActionListener(new ActionListener() {
622: public void actionPerformed(ActionEvent ae) {
623: try {
624: saveFilesAndEmptyCaches(sf);
625: unlock(sf.getFileOrDirectory(), false);
626: refreshFilesFromFileSystem(sf);
627: } catch (Exception e) {
628: JOptionPane.showMessageDialog(
629: MainEditorFrame.instance, ""
630: + e.getMessage(),
631: "SVN unlock error",
632: JOptionPane.ERROR_MESSAGE);
633: }
634: }
635: });
636:
637: m.addSeparator();
638:
639: // read only operation
640: JMenuItem add = new JMenuItem(
641: "add new files to cvs (must be commited)",
642: Icons.sharedPlus);
643: m.add(add);
644: add.addActionListener(new ActionListener() {
645: public void actionPerformed(ActionEvent ae) {
646: try {
647: saveFilesAndEmptyCaches(sf);
648: addRecurse(sf.getFileOrDirectory());
649: } catch (Exception e) {
650: JOptionPane.showMessageDialog(
651: MainEditorFrame.instance, ""
652: + e.getMessage(), "SVN add error",
653: JOptionPane.ERROR_MESSAGE);
654: }
655: }
656: });
657:
658: final JMenuItem delete = new JMenuItem(
659: "delete (must be commited)", Icons.sharedCross);
660: //m.addSeparator();
661: m.add(delete);
662: delete.addActionListener(new ActionListener() {
663: public void actionPerformed(ActionEvent ae) {
664: try {
665: int rep = JOptionPane
666: .showConfirmDialog(
667: MainEditorFrame.instance,
668: "The local files will be deleted (recursively). Are you sure ?",
669: "Deletion confirmation",
670: JOptionPane.YES_NO_CANCEL_OPTION);
671: if (rep != JOptionPane.YES_OPTION)
672: return;
673:
674: saveFilesAndEmptyCaches(sf);
675:
676: // this also deletes the file in the os system
677: delete(sf.getFileOrDirectory());
678:
679: // refresh ide view
680: MainEditorFrame.instance.sourcesTreePanel
681: .getTreeModel()
682: .scanForDifferencesWithFileSystem(sf);
683: MainEditorFrame.instance.sourcesTreePanel
684: .updateTree();
685: } catch (Exception e) {
686: JOptionPane.showMessageDialog(
687: MainEditorFrame.instance, ""
688: + e.getMessage(),
689: "SVN delete error",
690: JOptionPane.ERROR_MESSAGE);
691: }
692: }
693: });
694:
695: final JMenuItem revert = new JMenuItem(
696: "revert (cancels local modifications, must be commited)",
697: Icons.sharedLeftArrow);
698: //m.addSeparator();
699: m.add(revert);
700: revert.addActionListener(new ActionListener() {
701: public void actionPerformed(ActionEvent ae) {
702: try {
703: int rep = JOptionPane
704: .showConfirmDialog(
705: MainEditorFrame.instance,
706: "The local modifications will be reverted (ignored). Are you sure ?",
707: "Revert confirmation",
708: JOptionPane.YES_NO_CANCEL_OPTION);
709: if (rep != JOptionPane.YES_OPTION)
710: return;
711:
712: saveFilesAndEmptyCaches(sf);
713: // this reverts the file in the os system
714: revert(sf.getFileOrDirectory());
715:
716: // refresh ide view
717: MainEditorFrame.instance.sourcesTreePanel
718: .getTreeModel()
719: .scanForDifferencesWithFileSystem(sf);
720: MainEditorFrame.instance.sourcesTreePanel
721: .updateTree();
722: } catch (Exception e) {
723: JOptionPane.showMessageDialog(
724: MainEditorFrame.instance, ""
725: + e.getMessage(),
726: "SVN revert error",
727: JOptionPane.ERROR_MESSAGE);
728: }
729: }
730: });
731:
732: // writes back in the store
733: JMenuItem commit = new JMenuItem(
734: "commit (perform pending changes, sends data to server)",
735: Icons.sharedRightArrow);
736: commit.setToolTipText("Hold Shift to use an empty comment");
737: m.addSeparator();
738: m.add(commit);
739: commit.addActionListener(new ActionListener() {
740: public void actionPerformed(ActionEvent ae) {
741: try {
742: String comment = null;
743: int isS = ae.getModifiers() & ae.SHIFT_MASK;
744: if (isS == ae.SHIFT_MASK)
745: comment = "";
746:
747: saveFilesAndEmptyCaches(sf);
748: commit(sf.getFileOrDirectory(), comment);
749: } catch (Exception e) {
750: JOptionPane.showMessageDialog(
751: MainEditorFrame.instance, ""
752: + e.getMessage(),
753: "SVN commit error",
754: JOptionPane.ERROR_MESSAGE);
755: }
756: }
757: });
758:
759: JMenuItem status1 = new JMenuItem(
760: "status (shows only changed files)", Icons
761: .createHelpIcon(16, true));
762: m.addSeparator();
763: m.add(status1);
764: status1.addActionListener(new ActionListener() {
765: public void actionPerformed(ActionEvent ae) {
766: try {
767: saveFilesAndEmptyCaches(sf);
768: status(sf.getFileOrDirectory(), false);
769: } catch (Exception e) {
770: JOptionPane.showMessageDialog(
771: MainEditorFrame.instance, ""
772: + e.getMessage(),
773: "SVN status error",
774: JOptionPane.ERROR_MESSAGE);
775: }
776: }
777: });
778:
779: JMenuItem status = new JMenuItem(
780: "detailled status (shows all files)");
781: m.add(status);
782: status.addActionListener(new ActionListener() {
783: public void actionPerformed(ActionEvent ae) {
784: try {
785: saveFilesAndEmptyCaches(sf);
786: status(sf.getFileOrDirectory(), true);
787: } catch (Exception e) {
788: JOptionPane.showMessageDialog(
789: MainEditorFrame.instance, ""
790: + e.getMessage(),
791: "SVN status error",
792: JOptionPane.ERROR_MESSAGE);
793: }
794: }
795: });
796:
797: JMenuItem log = new JMenuItem("detailled revisions log",
798: new Icons.EyeIcon(16, 16, true));
799: m.add(log);
800: log.addActionListener(new ActionListener() {
801: public void actionPerformed(ActionEvent ae) {
802: try {
803: saveFilesAndEmptyCaches(sf);
804: log(sf.getFileOrDirectory(), true);
805: } catch (Exception e) {
806: JOptionPane.showMessageDialog(
807: MainEditorFrame.instance, ""
808: + e.getMessage(), "SVN log error",
809: JOptionPane.ERROR_MESSAGE);
810: }
811: }
812: });
813:
814: JMenuItem info = new JMenuItem("detailled repository info");
815: m.add(info);
816: info.addActionListener(new ActionListener() {
817: public void actionPerformed(ActionEvent ae) {
818: try {
819: saveFilesAndEmptyCaches(sf);
820: info(sf.getFileOrDirectory());
821: } catch (Exception e) {
822: JOptionPane.showMessageDialog(
823: MainEditorFrame.instance, ""
824: + e.getMessage(), "SVN info error",
825: JOptionPane.ERROR_MESSAGE);
826: }
827: }
828: });
829:
830: JMenuItem cleanup = new JMenuItem("cleanup");
831: m.addSeparator();
832: m.add(cleanup);
833: cleanup.addActionListener(new ActionListener() {
834: public void actionPerformed(ActionEvent ae) {
835: try {
836: saveFilesAndEmptyCaches(sf);
837: cleanup(sf.getFileOrDirectory());
838: } catch (Exception e) {
839: JOptionPane.showMessageDialog(
840: MainEditorFrame.instance, ""
841: + e.getMessage(),
842: "SVN cleanup error",
843: JOptionPane.ERROR_MESSAGE);
844: }
845: }
846: });
847:
848: return m;
849: }
850:
851: /*
852: blame (praise, annotate, ann)
853: cat If you want to examine an earlier version of a file and not necessarily the differences between two files, you can use svn cat: (svn cat --revision 2 rules.txt)
854: . checkout (co)
855: . cleanup
856: copy (cp)
857: . delete (del, remove, rm)
858: diff (di) If two revision numbers, separated by a colon, are passed via --revision (-r), then the two revisions are directly compared.
859: ($ svn diff --revision 2:3 rules.txt)
860: export
861: . import
862: . list (ls) The svn list command shows you what files are in a repository directory without actually downloading the files to your local machine:
863: log
864: merge
865: mkdir
866: move (mv, rename, ren)
867: propdel (pdel, pd)
868: propedit (pedit, pe)
869: propget (pget, pg)
870: proplist (plist, pl)
871: propset (pset, ps)
872: resolved
873: switch (sw)
874: */
875:
876: }
|