Index: src/org/netbeans/modules/vcscore/Bundle.properties =================================================================== RCS file: /cvs/vcscore/src/org/netbeans/modules/vcscore/Bundle.properties,v retrieving revision 1.25 diff -c -r1.25 Bundle.properties *** src/org/netbeans/modules/vcscore/Bundle.properties 6 Aug 2003 15:32:33 -0000 1.25 --- src/org/netbeans/modules/vcscore/Bundle.properties 28 Jan 2004 18:06:56 -0000 *************** *** 54,60 **** EXC_CannotDelete=Cannot delete VCS file {0} in {1}. EXC_CannotDeleteReadOnly=File {0} cannot be deleted because it is read-only. EXC_CannotLockReadOnly=File {0} cannot be locked because it is read-only. ! MSG_UnableToCreateDirectory=Unable To Create Directory {0}. --- 54,60 ---- EXC_CannotDelete=Cannot delete VCS file {0} in {1}. EXC_CannotDeleteReadOnly=File {0} cannot be deleted because it is read-only. EXC_CannotLockReadOnly=File {0} cannot be locked because it is read-only. ! EXC_file_is_being_modified=File {0} can be altered by a running VCS command, it's modification in the IDE is remporarily disabled. MSG_UnableToCreateDirectory=Unable To Create Directory {0}. Index: src/org/netbeans/modules/vcscore/VcsAction.java =================================================================== RCS file: /cvs/vcscore/src/org/netbeans/modules/vcscore/VcsAction.java,v retrieving revision 1.78 diff -c -r1.78 VcsAction.java *** src/org/netbeans/modules/vcscore/VcsAction.java 16 Sep 2003 11:25:08 -0000 1.78 --- src/org/netbeans/modules/vcscore/VcsAction.java 28 Jan 2004 18:06:57 -0000 *************** *** 692,697 **** --- 692,699 ---- * @param fos the collection of FileObjects */ public static void assureFilesSaved(Collection fos) { + DataObject[] modified = DataObject.getRegistry().getModified(); + if (modified.length == 0) return ; Collection folders = new LinkedList(); boolean wasSaved = false; for (Iterator it = fos.iterator(); it.hasNext(); ) { *************** *** 719,725 **** } } if (!folders.isEmpty()) { ! DataObject[] modified = DataObject.getRegistry().getModified(); for (int i = 0; i < modified.length; i++) { DataObject dobj = modified[i]; SaveCookie sc = (SaveCookie) dobj.getCookie(SaveCookie.class); --- 721,730 ---- } } if (!folders.isEmpty()) { ! if (wasSaved) { ! // Somethig was saved, need to get the list of modified objects again. ! modified = DataObject.getRegistry().getModified(); ! } for (int i = 0; i < modified.length; i++) { DataObject dobj = modified[i]; SaveCookie sc = (SaveCookie) dobj.getCookie(SaveCookie.class); Index: src/org/netbeans/modules/vcscore/VcsFileSystem.java =================================================================== RCS file: /cvs/vcscore/src/org/netbeans/modules/vcscore/VcsFileSystem.java,v retrieving revision 1.229 diff -c -r1.229 VcsFileSystem.java *** src/org/netbeans/modules/vcscore/VcsFileSystem.java 22 Aug 2003 20:50:52 -0000 1.229 --- src/org/netbeans/modules/vcscore/VcsFileSystem.java 28 Jan 2004 18:06:58 -0000 *************** *** 381,386 **** --- 381,388 ---- private String missingFolderStatus = null; private Collection notMissingableFileStatuses = Collections.EMPTY_SET; private Collection notMissingableFolderStatuses = Collections.EMPTY_SET; + + private Map lockedFilesToBeModified; private Boolean createRuntimeCommands = Boolean.TRUE; *************** *** 1509,1514 **** --- 1511,1517 ---- * of this class is created and after deserialization. Subclasses should call super.init(). */ protected void init() { + lockedFilesToBeModified = new HashMap(); displayName = computeDisplayName(); D.deb ("init()"); // NOI18N localFilenameFilter = new LocalFilenameFilter(); *************** *** 3390,3395 **** --- 3393,3456 ---- // /** + * Lock the files so that they can not be modified in the IDE. + * This is necessary for commands, that make changes to the processed files. + * It's crutial, that the file does not get modified twice - externally via + * the update command and internally (e.g. through the Editor). + * One MUST call {@link #unlockFilesToBeModified} after the command + * finish. + * @param path The path of the file to be locked or directory in which all + * files will be locked. + * @param recursively Whether the files in directories should be locked recursively. + */ + public void lockFilesToBeModified(String path, boolean recursively) { + synchronized (lockedFilesToBeModified) { + // Multiple locks are not considered. It's locked just once. + lockedFilesToBeModified.put(path, recursively ? Boolean.TRUE : Boolean.FALSE); + } + } + + /** + * Unlock the files that were previously locked by {@link #lockFilesToBeModified} + * method. It's necessary to call this method with appropriate arguments after + * the command finish so that the user can edit the files. + */ + public void unlockFilesToBeModified(String path, boolean recursively) { + synchronized (lockedFilesToBeModified) { + lockedFilesToBeModified.remove(path); + } + } + + /** Check whether the provided name is locked for modification. + * If yes, IOException is thrown. */ + private void checkModificationLock(final String name) throws IOException { + boolean isLocked; + synchronized (lockedFilesToBeModified) { + isLocked = lockedFilesToBeModified.get(name) != null; + if (!isLocked) { + for (Iterator it = lockedFilesToBeModified.keySet().iterator(); it.hasNext(); ) { + String path = (String) it.next(); + if (name.startsWith(path) && name.charAt(path.length()) == '/') { + boolean recursively = ((Boolean) lockedFilesToBeModified.get(path)).booleanValue(); + // either we lock it recursively or there are no more path separators '/': + isLocked = (recursively || name.indexOf('/', path.length() + 1) < 0); + } + } + } + } + if (isLocked) { + IOException exc = new IOException("File "+name+" can be altered by a running VCS command, it's modification in the IDE is remporarily disabled.") { + // It's necessary to define localized message separately, so that it's written to the Status bar !!!!!! See issue #9069. + public String getLocalizedMessage() { + return NbBundle.getMessage (VcsFileSystem.class, "EXC_file_is_being_modified", name); + } + }; + //exc = (IOException) ErrorManager.getDefault().annotate(exc, NbBundle.getMessage (VcsFileSystem.class, "EXC_file_is_being_modified", name)); + throw exc; + } + } + + /** * Should be called when the modification in a file or folder is expected * and its content should be refreshed. */ *************** *** 3984,3989 **** --- 4045,4051 ---- public void lock (String name_) throws IOException { //System.out.println("lock("+name_+")"); if (!isImportant(name_)) return; // ignore locking of unimportant files + checkModificationLock(name_); final String name = name_; //final VcsFileSystem current = this; final File file = getFile (name); Index: src/org/netbeans/modules/vcscore/cmdline/ExecuteCommand.java =================================================================== RCS file: /cvs/vcscore/src/org/netbeans/modules/vcscore/cmdline/ExecuteCommand.java,v retrieving revision 1.62 diff -c -r1.62 ExecuteCommand.java *** src/org/netbeans/modules/vcscore/cmdline/ExecuteCommand.java 8 Aug 2003 09:22:22 -0000 1.62 --- src/org/netbeans/modules/vcscore/cmdline/ExecuteCommand.java 28 Jan 2004 18:06:59 -0000 *************** *** 789,797 **** String[] allArgs = VcsUtilities.getQuotedArguments(exec); String first = allArgs[0]; //E.deb("first = "+first); // NOI18N ! boolean disableRefresh = VcsCommandIO.getBooleanProperty(cmd, VcsCommand.PROPERTY_CHECK_FOR_MODIFICATIONS); ! if (disableRefresh) fileSystem.disableRefresh(); try { if (first != null && (first.toLowerCase().endsWith(".class"))) {// NOI18N String[] args = new String[allArgs.length - 1]; System.arraycopy(allArgs, 1, args, 0, args.length); --- 789,816 ---- String[] allArgs = VcsUtilities.getQuotedArguments(exec); String first = allArgs[0]; //E.deb("first = "+first); // NOI18N ! boolean checkForModification = VcsCommandIO.getBooleanProperty(cmd, VcsCommand.PROPERTY_CHECK_FOR_MODIFICATIONS); ! Collection processingFiles = null; ! if (checkForModification) { ! processingFiles = getFiles(); ! fileSystem.disableRefresh(); ! for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { ! fileSystem.lockFilesToBeModified((String) it.next(), true); ! } ! } try { + if (checkForModification) { + // It's crucial to once more save any possibly modified objects + // after we have locked them. + List fileObjects = new ArrayList(processingFiles.size()); + for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { + FileObject fo = fileSystem.findResource((String) it.next()); + if (fo != null) { + fileObjects.add(fo); + } + } + VcsAction.assureFilesSaved(fileObjects); + } if (first != null && (first.toLowerCase().endsWith(".class"))) {// NOI18N String[] args = new String[allArgs.length - 1]; System.arraycopy(allArgs, 1, args, 0, args.length); *************** *** 800,806 **** runCommand(execs); } } finally { ! if (disableRefresh) fileSystem.enableRefresh(); String tempFilePath = (String) vars.get(Variables.TEMPORARY_FILE); if (tempFilePath != null) new File(tempFilePath).delete(); } --- 819,830 ---- runCommand(execs); } } finally { ! if (checkForModification) { ! fileSystem.enableRefresh(); ! for (Iterator it = processingFiles.iterator(); it.hasNext(); ) { ! fileSystem.unlockFilesToBeModified((String) it.next(), true); ! } ! } String tempFilePath = (String) vars.get(Variables.TEMPORARY_FILE); if (tempFilePath != null) new File(tempFilePath).delete(); } Index: src/org/netbeans/modules/vcscore/commands/CommandCustomizationSupport.java =================================================================== RCS file: /cvs/vcscore/src/org/netbeans/modules/vcscore/commands/CommandCustomizationSupport.java,v retrieving revision 1.12 diff -c -r1.12 CommandCustomizationSupport.java *** src/org/netbeans/modules/vcscore/commands/CommandCustomizationSupport.java 19 Aug 2003 14:23:43 -0000 1.12 --- src/org/netbeans/modules/vcscore/commands/CommandCustomizationSupport.java 28 Jan 2004 18:06:59 -0000 *************** *** 545,551 **** } } } - */ private static void checkForModifications(VcsFileSystem fileSystem, VcsCommandExecutor vce) { if (VcsCommandIO.getBooleanProperty(vce.getCommand(), VcsCommand.PROPERTY_CHECK_FOR_MODIFICATIONS)) { --- 545,550 ---- *************** *** 556,565 **** /* org.openide.filesystems.FileObject fo = fileSystem.findResource(path); System.out.println("fo("+path+") = "+fo); ! */ } } } /** --- 555,565 ---- /* org.openide.filesystems.FileObject fo = fileSystem.findResource(path); System.out.println("fo("+path+") = "+fo); ! *//* } } } + */ /**