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:
042: package org.netbeans.modules.subversion;
043:
044: import org.openide.util.NbBundle;
045:
046: import java.util.*;
047: import java.io.Serializable;
048: import java.io.File;
049: import org.tigris.subversion.svnclientadapter.ISVNStatus;
050: import org.tigris.subversion.svnclientadapter.SVNClientException;
051: import org.tigris.subversion.svnclientadapter.SVNNodeKind;
052:
053: /**
054: * Immutable class encapsulating status of a file.
055: *
056: * @author Maros Sandor
057: */
058: public class FileInformation implements Serializable {
059:
060: private static final long serialVersionUID = 1L;
061:
062: /**
063: * There is nothing known about the file, it may not even exist.
064: */
065: public static final int STATUS_UNKNOWN = 0;
066:
067: /**
068: * The file is not managed by the module, i.e. the user does not wish it to be under control of this
069: * versioning system module. All files except files under versioned roots have this status.
070: */
071: public static final int STATUS_NOTVERSIONED_NOTMANAGED = 1;
072:
073: /**
074: * The file exists locally but is NOT under version control because it should not be (i.e. is has
075: * the Ignore property set or resides under an excluded folder). The file itself IS under a versioned root.
076: */
077: public static final int STATUS_NOTVERSIONED_EXCLUDED = 2;
078:
079: /**
080: * The file exists locally but is NOT under version control, mostly because it has not been added
081: * to the repository yet.
082: */
083: public static final int STATUS_NOTVERSIONED_NEWLOCALLY = 4;
084:
085: /**
086: * The file is under version control and is in sync with repository.
087: */
088: public static final int STATUS_VERSIONED_UPTODATE = 8;
089:
090: /**
091: * The file is modified locally and was not yet modified in repository.
092: */
093: public static final int STATUS_VERSIONED_MODIFIEDLOCALLY = 16;
094:
095: /**
096: * The file was not modified locally but an updated version exists in repository.
097: */
098: public static final int STATUS_VERSIONED_MODIFIEDINREPOSITORY = 32;
099:
100: /**
101: * Merging during update resulted in merge conflict. Conflicts in the local copy must be resolved before
102: * the file can be commited.
103: */
104: public static final int STATUS_VERSIONED_CONFLICT = 64;
105:
106: /**
107: * The file was modified both locally and remotely and these changes may or may not result in
108: * merge conflict.
109: */
110: public static final int STATUS_VERSIONED_MERGE = 128;
111:
112: /**
113: * The file does NOT exist locally and exists in repository, it has beed removed locally, waits
114: * for commit.
115: */
116: public static final int STATUS_VERSIONED_REMOVEDLOCALLY = 256;
117:
118: /**
119: * The file does NOT exist locally but exists in repository and has not yet been downloaded.
120: */
121: public static final int STATUS_VERSIONED_NEWINREPOSITORY = 512;
122:
123: /**
124: * The file has been removed from repository.
125: */
126: public static final int STATUS_VERSIONED_REMOVEDINREPOSITORY = 1024;
127:
128: /**
129: * The file does NOT exist locally and exists in repository, it has beed removed locally.
130: */
131: public static final int STATUS_VERSIONED_DELETEDLOCALLY = 2048;
132:
133: /**
134: * The file exists locally and has beed scheduled for addition to repository. This status represents
135: * state after the 'add' command.
136: */
137: public static final int STATUS_VERSIONED_ADDEDLOCALLY = 4096;
138:
139: /**
140: * The file has an active lock against it.
141: */
142: public static final int STATUS_LOCKED = 8192;
143:
144: public static final int STATUS_ALL = ~0;
145:
146: /**
147: * All statuses except <tt>STATUS_NOTVERSIONED_NOTMANAGED</tt>
148: *
149: * <p>Note: it covers ignored files.
150: */
151: public static final int STATUS_MANAGED = STATUS_ALL
152: & ~STATUS_NOTVERSIONED_NOTMANAGED;
153:
154: /** Has local metadata under .svn/ */
155: public static final int STATUS_VERSIONED = STATUS_VERSIONED_UPTODATE
156: | STATUS_VERSIONED_MODIFIEDLOCALLY
157: | STATUS_VERSIONED_MODIFIEDINREPOSITORY
158: | STATUS_VERSIONED_CONFLICT
159: | STATUS_VERSIONED_MERGE
160: | STATUS_VERSIONED_REMOVEDLOCALLY
161: | STATUS_VERSIONED_REMOVEDINREPOSITORY
162: | STATUS_VERSIONED_DELETEDLOCALLY
163: | STATUS_VERSIONED_ADDEDLOCALLY;
164:
165: public static final int STATUS_IN_REPOSITORY = STATUS_VERSIONED_UPTODATE
166: | STATUS_VERSIONED_MODIFIEDLOCALLY
167: | STATUS_VERSIONED_MODIFIEDINREPOSITORY
168: | STATUS_VERSIONED_CONFLICT
169: | STATUS_VERSIONED_MERGE
170: | STATUS_VERSIONED_REMOVEDLOCALLY
171: | STATUS_VERSIONED_NEWINREPOSITORY
172: | STATUS_VERSIONED_REMOVEDINREPOSITORY
173: | STATUS_VERSIONED_DELETEDLOCALLY;
174:
175: public static final int STATUS_LOCAL_CHANGE = FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY
176: | FileInformation.STATUS_VERSIONED_ADDEDLOCALLY
177: | FileInformation.STATUS_VERSIONED_CONFLICT
178: | FileInformation.STATUS_VERSIONED_DELETEDLOCALLY
179: | FileInformation.STATUS_VERSIONED_MERGE
180: | FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY
181: | FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY;
182:
183: /**
184: * Modified, in conflict, scheduled for removal or addition;
185: * or deleted but with existing entry record.
186: */
187: public static final int STATUS_REVERTIBLE_CHANGE = FileInformation.STATUS_VERSIONED_ADDEDLOCALLY
188: | FileInformation.STATUS_VERSIONED_CONFLICT
189: | FileInformation.STATUS_VERSIONED_MERGE
190: | FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY
191: | FileInformation.STATUS_VERSIONED_DELETEDLOCALLY
192: | FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY;
193:
194: public static final int STATUS_REMOTE_CHANGE = FileInformation.STATUS_VERSIONED_MERGE
195: | FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY
196: | FileInformation.STATUS_VERSIONED_NEWINREPOSITORY
197: | FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY;
198:
199: /**
200: * Status constant.
201: */
202: private final int status;
203:
204: /**
205: * Status constant for properties.
206: */
207: private final int propStatus;
208:
209: /**
210: * Entry from the .svn directory, if it exists and has been read.
211: */
212: private transient ISVNStatus entry;
213:
214: /**
215: * Directory indicator.
216: */
217: private final boolean isDirectory;
218:
219: private static final String STATUS_UNKNOWN_EXT = "W"; // NOI18N
220: private static final String STATUS_NOTVERSIONED_NOTMANAGED_EXT = "Z"; // NOI18N
221: private static final String STATUS_NOTVERSIONED_EXCLUDED_EXT = "I"; // NOI18N
222: private static final String STATUS_NOTVERSIONED_NEWLOCALLY_EXT = "?"; // NOI18N
223: private static final String STATUS_VERSIONED_UPTODATE_EXT = "S"; // NOI18N
224: private static final String STATUS_VERSIONED_MODIFIEDLOCALLY_EXT = "M"; // NOI18N
225: private static final String STATUS_VERSIONED_MODIFIEDINREPOSITORY_EXT = "G"; // NOI18N
226: private static final String STATUS_VERSIONED_CONFLICT_EXT = "C"; // NOI18N
227: private static final String STATUS_VERSIONED_MERGE_EXT = "P"; // NOI18N
228: private static final String STATUS_VERSIONED_REMOVEDLOCALLY_EXT = "R"; // NOI18N
229: private static final String STATUS_VERSIONED_NEWINREPOSITORY_EXT = "N"; // NOI18N
230: private static final String STATUS_VERSIONED_REMOVEDINREPOSITORY_EXT = "D"; // NOI18N
231: private static final String STATUS_VERSIONED_DELETEDLOCALLY_EXT = "E"; // NOI18N
232: private static final String STATUS_VERSIONED_ADDEDLOCALLY_EXT = "A"; // NOI18N
233:
234: // for debuging purposes
235: private final Exception origin;
236:
237: /**
238: * For deserialization purposes only.
239: */
240: public FileInformation() {
241: status = 0;
242: propStatus = 0;
243: isDirectory = false;
244: origin = new RuntimeException("allocated at:"); // NOI18N
245: }
246:
247: private FileInformation(int status, int propStatus,
248: ISVNStatus entry, boolean isDirectory) {
249: this .status = status;
250: this .propStatus = propStatus;
251: this .entry = entry;
252: this .isDirectory = isDirectory;
253: origin = new RuntimeException("allocated at:"); // NOI18N
254: }
255:
256: FileInformation(int status, ISVNStatus entry) {
257: this (status, 0, entry, entry.getNodeKind() == SVNNodeKind.DIR);
258: }
259:
260: FileInformation(int status, boolean isDirectory) {
261: this (status, 0, null, isDirectory);
262: }
263:
264: FileInformation(int status, int propStatus, boolean isDirectory) {
265: this (status, propStatus, null, isDirectory);
266: }
267:
268: /**
269: * Retrieves the status constant representing status of the file.
270: *
271: * @return one of status constants
272: */
273: public int getStatus() {
274: return status;
275: }
276:
277: public boolean isDirectory() {
278: return isDirectory;
279: }
280:
281: /**
282: * Retrieves file's Entry.
283: *
284: * @param file file this information belongs to or null if you do not want the entry to be read from disk
285: * in case it is not loaded yet
286: * @return Status parsed entry form the .svn/entries file or null if the file does not exist,
287: * is not versioned or its entry is invalid
288: */
289: public ISVNStatus getEntry(File file) {
290: if (entry == null && file != null) {
291: readEntry(file);
292: }
293: return entry;
294: }
295:
296: private void readEntry(File file) {
297: try {
298: entry = Subversion.getInstance().getClient(true)
299: .getSingleStatus(file);
300: } catch (SVNClientException e) {
301: // no entry for this file, ignore
302: }
303: }
304:
305: /**
306: * Returns localized text representation of status.
307: *
308: * @return status name, for multistatuses prefers local
309: * status name.
310: */
311: public String getStatusText() {
312: return getStatusText(~0);
313: }
314:
315: /**
316: * Returns localized text representation of status.
317: *
318: * @param displayStatuses statuses bitmask
319: *
320: * @return status name, for multistatuses prefers local
321: * status name, for masked <tt>""</tt>.
322: */
323: public String getStatusText(int displayStatuses) {
324: int status = this .status & displayStatuses;
325: ResourceBundle loc = NbBundle.getBundle(FileInformation.class);
326: if (status == FileInformation.STATUS_UNKNOWN) {
327: return loc.getString("CTL_FileInfoStatus_Unknown");
328: } else if (match(status,
329: FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) {
330: return loc.getString("CTL_FileInfoStatus_Excluded");
331: } else if (match(status,
332: FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) {
333: return loc.getString("CTL_FileInfoStatus_NewLocally");
334: } else if (match(status,
335: FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) {
336: if (entry != null && entry.isCopied()) {
337: return loc
338: .getString("CTL_FileInfoStatus_AddedLocallyCopied");
339: }
340: return loc.getString("CTL_FileInfoStatus_AddedLocally");
341: } else if (match(status,
342: FileInformation.STATUS_VERSIONED_UPTODATE)) {
343: return loc.getString("CTL_FileInfoStatus_UpToDate");
344: } else if (match(status,
345: FileInformation.STATUS_VERSIONED_CONFLICT)) {
346: return loc.getString("CTL_FileInfoStatus_Conflict");
347: } else if (match(status, FileInformation.STATUS_VERSIONED_MERGE)) {
348: return loc.getString("CTL_FileInfoStatus_Merge");
349: } else if (match(status,
350: FileInformation.STATUS_VERSIONED_DELETEDLOCALLY)) {
351: return loc.getString("CTL_FileInfoStatus_DeletedLocally");
352: } else if (match(status,
353: FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY)) {
354: return loc.getString("CTL_FileInfoStatus_RemovedLocally");
355: } else if (match(status,
356: FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) {
357: return loc.getString("CTL_FileInfoStatus_ModifiedLocally");
358:
359: } else if (match(status,
360: FileInformation.STATUS_VERSIONED_NEWINREPOSITORY)) {
361: return loc.getString("CTL_FileInfoStatus_NewInRepository");
362: } else if (match(status,
363: FileInformation.STATUS_VERSIONED_MODIFIEDINREPOSITORY)) {
364: return loc
365: .getString("CTL_FileInfoStatus_ModifiedInRepository");
366: } else if (match(status,
367: FileInformation.STATUS_VERSIONED_REMOVEDINREPOSITORY)) {
368: return loc
369: .getString("CTL_FileInfoStatus_RemovedInRepository");
370: } else {
371: return ""; // NOI18N
372: }
373: }
374:
375: /**
376: * @return short status name for local changes, for remote
377: * changes returns <tt>""</tt>
378: */
379: public String getShortStatusText() {
380: ResourceBundle loc = NbBundle.getBundle(FileInformation.class);
381: if (match(status, FileInformation.STATUS_NOTVERSIONED_EXCLUDED)) {
382: return loc.getString("CTL_FileInfoStatus_Excluded_Short");
383: } else if (match(status,
384: FileInformation.STATUS_NOTVERSIONED_NEWLOCALLY)) {
385: return loc.getString("CTL_FileInfoStatus_NewLocally_Short");
386: } else if (match(status,
387: FileInformation.STATUS_VERSIONED_ADDEDLOCALLY)) {
388: if (entry != null && entry.isCopied()) {
389: return loc
390: .getString("CTL_FileInfoStatus_AddedLocallyCopied_Short");
391: }
392: return loc
393: .getString("CTL_FileInfoStatus_AddedLocally_Short");
394: } else if (status == FileInformation.STATUS_VERSIONED_REMOVEDLOCALLY) {
395: return loc
396: .getString("CTL_FileInfoStatus_RemovedLocally_Short");
397: } else if (status == FileInformation.STATUS_VERSIONED_DELETEDLOCALLY) {
398: return loc
399: .getString("CTL_FileInfoStatus_DeletedLocally_Short");
400: } else if (match(status,
401: FileInformation.STATUS_VERSIONED_MODIFIEDLOCALLY)) {
402: return loc
403: .getString("CTL_FileInfoStatus_ModifiedLocally_Short");
404: } else if (match(status,
405: FileInformation.STATUS_VERSIONED_CONFLICT)) {
406: return loc.getString("CTL_FileInfoStatus_Conflict_Short");
407: } else {
408: return ""; // NOI18N
409: }
410: }
411:
412: private static boolean match(int status, int mask) {
413: return (status & mask) != 0;
414: }
415:
416: public String toString() {
417: return "Text: " + status + " " + getStatusText(status)
418: + "\nProp: " + propStatus + " "
419: + getStatusText(propStatus); // NOI18N
420: }
421: }
|