001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.mercurial.ui.create;
042:
043: import java.io.File;
044: import java.util.Calendar;
045: import java.util.logging.Level;
046: import org.netbeans.modules.mercurial.HgException;
047: import org.netbeans.modules.mercurial.Mercurial;
048: import org.netbeans.modules.mercurial.OutputLogger;
049: import org.netbeans.modules.mercurial.util.HgUtils;
050: import org.netbeans.modules.versioning.spi.VCSContext;
051: import org.netbeans.modules.versioning.util.Utils;
052: import javax.swing.*;
053: import java.awt.event.ActionEvent;
054: import java.util.HashMap;
055: import java.util.LinkedList;
056: import java.util.List;
057: import java.util.Map;
058: import org.netbeans.modules.mercurial.FileInformation;
059: import org.netbeans.modules.mercurial.FileStatusCache;
060: import org.netbeans.modules.mercurial.HgProgressSupport;
061: import org.netbeans.modules.mercurial.util.HgCommand;
062: import org.netbeans.modules.mercurial.util.HgProjectUtils;
063: import org.netbeans.modules.mercurial.ui.actions.ContextAction;
064: import org.openide.util.RequestProcessor;
065: import org.openide.DialogDisplayer;
066: import org.openide.NotifyDescriptor;
067: import org.openide.util.NbBundle;
068: import org.netbeans.api.project.Project;
069: import org.openide.filesystems.FileUtil;
070: import org.openide.filesystems.FileObject;
071:
072: /**
073: * Create action for mercurial:
074: * hg init - create a new repository in the given directory
075: *
076: * @author John Rice
077: */
078: public class CreateAction extends ContextAction {
079:
080: private final VCSContext context;
081: Map<File, FileInformation> repositoryFiles = new HashMap<File, FileInformation>();
082:
083: public CreateAction(String name, VCSContext context) {
084: this .context = context;
085: putValue(Action.NAME, name);
086: }
087:
088: public boolean isEnabled() {
089: // If it is not a mercurial managed repository enable action
090: File root = HgUtils.getRootFile(context);
091: File[] files = context.getRootFiles().toArray(
092: new File[context.getRootFiles().size()]);
093: if (files == null || files.length == 0)
094: return false;
095:
096: if (root == null)
097: return true;
098: else
099: return false;
100: }
101:
102: private File getCommonAncestor(File firstFile, File secondFile) {
103: if (firstFile.equals(secondFile))
104: return firstFile;
105:
106: File tempFirstFile = firstFile;
107: while (tempFirstFile != null) {
108: File tempSecondFile = secondFile;
109: while (tempSecondFile != null) {
110: if (tempFirstFile.equals(tempSecondFile))
111: return tempSecondFile;
112: tempSecondFile = tempSecondFile.getParentFile();
113: }
114: tempFirstFile = tempFirstFile.getParentFile();
115: }
116: return null;
117: }
118:
119: private File getCommonAncestor(File[] files) {
120: File f1 = files[0];
121:
122: for (int i = 1; i < files.length; i++) {
123: f1 = getCommonAncestor(f1, files[i]);
124: if (f1 == null) {
125: Mercurial.LOG.log(Level.SEVERE,
126: "Unable to get common parent of {0} and {1} ", // NOI18N
127: new Object[] { f1.getAbsolutePath(),
128: files[i].getAbsolutePath() });
129: }
130:
131: }
132: return f1;
133: }
134:
135: public void performAction(ActionEvent e) {
136: final Mercurial hg = Mercurial.getInstance();
137:
138: final File[] files = context.getRootFiles().toArray(
139: new File[context.getRootFiles().size()]);
140: if (files == null || files.length == 0)
141: return;
142:
143: // If there is a .hg directory in an ancestor of any of the files in
144: // the context we fail.
145:
146: for (File file : files) {
147: if (!file.isDirectory())
148: file = file.getParentFile();
149: if (hg.getTopmostManagedParent(file) != null) {
150: Mercurial.LOG.log(Level.SEVERE,
151: "Found .hg directory in ancestor of {0} ", // NOI18N
152: file);
153: return;
154: }
155: }
156:
157: final Project proj = HgUtils.getProject(context);
158: final File projFile = HgUtils.getProjectFile(proj);
159:
160: if (projFile == null) {
161: OutputLogger logger = OutputLogger
162: .getLogger(Mercurial.MERCURIAL_OUTPUT_TAB_TITLE);
163: logger.outputInRed(NbBundle.getMessage(CreateAction.class,
164: "MSG_CREATE_TITLE")); // NOI18N
165: logger.outputInRed(NbBundle.getMessage(CreateAction.class,
166: "MSG_CREATE_TITLE_SEP")); // NOI18N
167: logger.outputInRed(NbBundle.getMessage(CreateAction.class,
168: "MSG_CREATE_NOT_SUPPORTED_INVIEW_INFO")); // NOI18N
169: logger.output(""); // NOI18N
170: JOptionPane.showMessageDialog(null, NbBundle.getMessage(
171: CreateAction.class,
172: "MSG_CREATE_NOT_SUPPORTED_INVIEW"),// NOI18N
173: NbBundle.getMessage(CreateAction.class,
174: "MSG_CREATE_NOT_SUPPORTED_INVIEW_TITLE"),// NOI18N
175: JOptionPane.INFORMATION_MESSAGE);
176: logger.closeLog();
177: return;
178: }
179: String projName = HgProjectUtils.getProjectName(projFile);
180: File root = null;
181:
182: root = getCommonAncestor(files);
183: root = getCommonAncestor(root, projFile);
184: if (root == null)
185: return;
186:
187: final File rootToManage = root;
188: final String prjName = projName;
189:
190: if (rootToManage.getAbsolutePath().indexOf(
191: projFile.getAbsolutePath()) != 0) {
192: OutputLogger logger = OutputLogger.getLogger(rootToManage
193: .getAbsolutePath());
194: logger.outputInRed(NbBundle.getMessage(CreateAction.class,
195: "MSG_CREATE_TITLE")); // NOI18N
196: logger.outputInRed(NbBundle.getMessage(CreateAction.class,
197: "MSG_CREATE_TITLE_SEP")); // NOI18N
198: logger.output(NbBundle.getMessage(CreateAction.class,
199: "MSG_CREATE_INFO1", projFile.getAbsolutePath())); // NOI18N
200: for (File f : files) {
201: if (f.getAbsolutePath().indexOf(
202: projFile.getAbsolutePath()) != 0) {
203: logger.output(" " + f.getAbsolutePath()); // NOI18N
204: }
205: }
206: logger
207: .output(NbBundle.getMessage(CreateAction.class,
208: "MSG_CREATE_INFO2", rootToManage
209: .getAbsolutePath())); // NOI18N
210: NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
211: NbBundle.getMessage(CreateAction.class,
212: "MSG_CREATE_CONFIRM_QUERY", rootToManage
213: .getAbsolutePath())); // NOI18N
214:
215: descriptor.setTitle(NbBundle.getMessage(CreateAction.class,
216: "MSG_CREATE_CONFIRM_TITLE")); // NOI18N
217: descriptor.setMessageType(JOptionPane.INFORMATION_MESSAGE);
218: descriptor.setOptionType(NotifyDescriptor.OK_CANCEL_OPTION);
219:
220: Object res = DialogDisplayer.getDefault()
221: .notify(descriptor);
222: if (res == NotifyDescriptor.CANCEL_OPTION) {
223: logger.outputInRed(NbBundle.getMessage(
224: CreateAction.class, "MSG_CREATE_CANCELED",
225: rootToManage.getAbsolutePath())); // NOI18N
226: logger.output(""); // NOI18N
227: return;
228: }
229: }
230:
231: RequestProcessor rp = hg.getRequestProcessor(rootToManage
232: .getAbsolutePath());
233:
234: HgProgressSupport supportCreate = new HgProgressSupport() {
235: public void perform() {
236:
237: try {
238: OutputLogger logger = getLogger();
239: if (rootToManage.getAbsolutePath().indexOf(
240: projFile.getAbsolutePath()) == 0) {
241: logger
242: .outputInRed(NbBundle.getMessage(
243: CreateAction.class,
244: "MSG_CREATE_TITLE")); // NOI18N
245: logger.outputInRed(NbBundle.getMessage(
246: CreateAction.class,
247: "MSG_CREATE_TITLE_SEP")); // NOI18N
248: }
249: logger.output(NbBundle.getMessage(
250: CreateAction.class, "MSG_CREATE_INIT",
251: prjName, rootToManage)); // NOI18N
252: HgCommand.doCreate(rootToManage, logger);
253: hg.versionedFilesChanged();
254: hg.refreshAllAnnotations();
255: } catch (HgException ex) {
256: NotifyDescriptor.Exception e = new NotifyDescriptor.Exception(
257: ex);
258: DialogDisplayer.getDefault().notifyLater(e);
259: }
260: }
261: };
262: supportCreate.start(rp, rootToManage.getAbsolutePath(),
263: org.openide.util.NbBundle.getMessage(
264: CreateAction.class, "MSG_Create_Progress")); // NOI18N
265:
266: HgProgressSupport supportAdd = new HgProgressSupport() {
267: public void perform() {
268: OutputLogger logger = getLogger();
269: try {
270: File[] files = HgUtils.getProjectRootFiles(proj);
271: FileStatusCache cache = hg.getFileStatusCache();
272: FileInformation fi = new FileInformation(
273: FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY,
274: null, false);
275:
276: for (int j = 0; j < files.length; j++) {
277: File rootFile = files[j];
278: Calendar start = Calendar.getInstance();
279: repositoryFiles = HgCommand.getUnknownStatus(
280: rootToManage, rootFile);
281: Calendar end = Calendar.getInstance();
282: Mercurial.LOG.log(Level.FINE,
283: "getUnknownStatus took {0} millisecs",
284: end.getTimeInMillis()
285: - start.getTimeInMillis()); // NOI18N
286: logger.output(NbBundle.getMessage(
287: CreateAction.class, "MSG_CREATE_ADD",
288: repositoryFiles.keySet().size(),
289: rootFile.getAbsolutePath())); // NOI18N
290: start = Calendar.getInstance();
291: cache.addToCache(repositoryFiles.keySet());
292: end = Calendar.getInstance();
293: Mercurial.LOG
294: .log(
295: Level.FINE,
296: "addUnknownsToCache took {0} millisecs",
297: end.getTimeInMillis()
298: - start
299: .getTimeInMillis()); // NOI18N
300: if (repositoryFiles.keySet().size() < OutputLogger.MAX_LINES_TO_PRINT) {
301: for (File f : repositoryFiles.keySet()) {
302: logger.output("\t"
303: + f.getAbsolutePath()); // NOI18N
304: }
305: }
306: }
307: HgUtils.createIgnored(rootToManage);
308: logger.output(""); // NOI18N
309: logger.outputInRed(NbBundle.getMessage(
310: CreateAction.class,
311: "MSG_CREATE_DONE_WARNING")); // NOI18N
312: } catch (HgException ex) {
313: NotifyDescriptor.Exception e = new NotifyDescriptor.Exception(
314: ex);
315: DialogDisplayer.getDefault().notifyLater(e);
316: } finally {
317: logger.outputInRed(NbBundle.getMessage(
318: CreateAction.class, "MSG_CREATE_DONE")); // NOI18N
319: logger.output(""); // NOI18N
320: }
321: }
322: };
323: supportAdd.start(rp, rootToManage.getAbsolutePath(),
324: org.openide.util.NbBundle.getMessage(
325: CreateAction.class, "MSG_Create_Add_Progress")); // NOI18N
326: }
327: }
|