001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012: package org.tmatesoft.svn.core.wc;
013:
014: import java.io.File;
015: import java.util.Date;
016: import java.util.Map;
017:
018: import org.tmatesoft.svn.core.SVNLock;
019: import org.tmatesoft.svn.core.SVNNodeKind;
020: import org.tmatesoft.svn.core.SVNURL;
021: import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
022: import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
023:
024: /**
025: * The <b>SVNStatus</b> class is used to provide detailed status information for
026: * a Working Copy item as a result of a status operation invoked by a
027: * doStatus() method of <b>SVNStatusClient</b>. <b>SVNStatus</b> objects are
028: * generated for each 'interesting' local item and depending on the doStatus() method
029: * in use either passed for notification to an <b>ISVNStatusHandler</b>
030: * implementation or such an object is just returned by the method as a
031: * status info for a single item.
032: *
033: * <p>
034: * Within the status handler implementation a developer decides how to interpret status
035: * information. For some purposes this way may be more flexible in comparison
036: * with calling doStatus() that returns an <b>SVNStatus</b> per one local item.
037: * However the latter one may be useful when needing to find out the status of
038: * the concrete item.
039: *
040: * <p>
041: *
042: * There are two approaches how to process <b>SVNStatus</b> objects:<br />
043: * 1. Implementing an <b>ISVNStatusHandler</b>:
044: * <pre class="javacode">
045: * <span class="javakeyword">import</span> org.tmatesoft.svn.core.wc.ISVNStatusHandler;
046: * <span class="javakeyword">import</span> org.tmatesoft.svn.core.wc.SVNStatus;
047: * <span class="javakeyword">import</span> org.tmatesoft.svn.core.wc.SVNStatusType;
048: * ...
049: *
050: * <span class="javakeyword">public class</span> MyCustomStatusHandler <span class="javakeyword">implements</span> ISVNStatusHandler {
051: * <span class="javakeyword">public void</span> handleStatus(SVNStatus status) {
052: * <span class="javacomment">//parse the item's contents status</span>
053: * <span class="javakeyword">if</span>(status.getContentsStatus() == SVNStatusType.STATUS_MODIFIED) {
054: * ...
055: * } <span class="javakeyword">else if</span>(status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) {
056: * ...
057: * }
058: * ...
059: * <span class="javacomment">//parse properties status</span>
060: * <span class="javakeyword">if</span>(status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) {
061: * ...
062: * }
063: * ...
064: * }
065: * }</pre><br />
066: * ...and providing a status handler implementation to an <b>SVNStatusClient</b>'s
067: * doStatus() method:
068: * <pre class="javacode">
069: * ...
070: * <span class="javakeyword">import</span> org.tmatesoft.svn.core.wc.SVNStatusClient;
071: * ...
072: *
073: * SVNStatusClient statusClient;
074: * ...
075: *
076: * statusClient.doStatus(...., <span class="javakeyword">new</span> MyCustomStatusHandler());
077: * ...</pre><br />
078: * 2. Or process an <b>SVNStatus</b> like this:
079: * <pre class="javacode">
080: * ...
081: * SVNStatus status = statusClient.doStatus(<span class="javakeyword">new</span> File(myPath), <span class="javakeyword">false</span>);
082: * <span class="javacomment">//parsing status info here</span>
083: * ...</pre>
084: * </p>
085: * <p>
086: * <b>SVNStatus</b>'s methods which names start with <code>getRemote</code> are relevant
087: * for remote status invocations - that is when a doStatus() method of <b>SVNStatusClient</b>
088: * is called with the flag <code>remote</code> set to <span class="javakeyword">true</span>.
089: *
090: * @version 1.1.1
091: * @author TMate Software Ltd.
092: * @see ISVNStatusHandler
093: * @see SVNStatusType
094: * @see <a target="_top" href="http://svnkit.com/kb/examples/">Examples</a>
095: */
096: public class SVNStatus {
097:
098: private SVNURL myURL;
099: private File myFile;
100: private SVNNodeKind myKind;
101: private SVNRevision myRevision;
102: private SVNRevision myCommittedRevision;
103: private Date myCommittedDate;
104: private String myAuthor;
105: private SVNStatusType myContentsStatus;
106: private SVNStatusType myPropertiesStatus;
107: private SVNStatusType myRemoteContentsStatus;
108: private SVNStatusType myRemotePropertiesStatus;
109: private boolean myIsLocked;
110: private boolean myIsCopied;
111: private boolean myIsSwitched;
112: private File myConflictNewFile;
113: private File myConflictOldFile;
114: private File myConflictWrkFile;
115: private File myPropRejectFile;
116: private String myCopyFromURL;
117: private SVNRevision myCopyFromRevision;
118: private SVNLock myRemoteLock;
119: private SVNLock myLocalLock;
120: private Map myEntryProperties;
121: private SVNRevision myRemoteRevision;
122: private SVNURL myRemoteURL;
123: private SVNNodeKind myRemoteKind;
124: private String myRemoteAuthor;
125: private Date myRemoteDate;
126: private Date myLocalContentsDate;
127: private Date myLocalPropertiesDate;
128: private SVNEntry myEntry;
129:
130: /**
131: * Constructs an <b>SVNStatus</b> object filling it with status information
132: * details.
133: *
134: * <p>
135: * Used by SVNKit internals to construct and initialize an
136: * <b>SVNStatus</b> object. It's not intended for users (from an API
137: * point of view).
138: *
139: * @param url item's repository location
140: * @param file item's path in a File representation
141: * @param kind item's node kind
142: * @param revision item's working revision
143: * @param committedRevision item's last changed revision
144: * @param committedDate item's last changed date
145: * @param author item's last commit author
146: * @param contentsStatus local status of item's contents
147: * @param propertiesStatus local status of item's properties
148: * @param remoteContentsStatus status of item's contents against a repository
149: * @param remotePropertiesStatus status of item's properties against a repository
150: * @param isLocked if the item is locked by the driver (not a user lock)
151: * @param isCopied if the item is added with history
152: * @param isSwitched if the item is switched to a different URL
153: * @param conflictNewFile temp file with latest changes from the repository
154: * @param conflictOldFile temp file just as the conflicting one was at the BASE revision
155: * @param conflictWrkFile temp file with all user's current local modifications
156: * @param projRejectFile temp file describing properties conflicts
157: * @param copyFromURL url of the item's ancestor from which the item was copied
158: * @param copyFromRevision item's ancestor revision from which the item was copied
159: * @param remoteLock item's lock in the repository
160: * @param localLock item's local lock
161: * @param entryProperties item's SVN specific '<entry' properties
162: */
163: public SVNStatus(SVNURL url, File file, SVNNodeKind kind,
164: SVNRevision revision, SVNRevision committedRevision,
165: Date committedDate, String author,
166: SVNStatusType contentsStatus,
167: SVNStatusType propertiesStatus,
168: SVNStatusType remoteContentsStatus,
169: SVNStatusType remotePropertiesStatus, boolean isLocked,
170: boolean isCopied, boolean isSwitched, File conflictNewFile,
171: File conflictOldFile, File conflictWrkFile,
172: File projRejectFile, String copyFromURL,
173: SVNRevision copyFromRevision, SVNLock remoteLock,
174: SVNLock localLock, Map entryProperties) {
175: myURL = url;
176: myFile = file;
177: myKind = kind == null ? SVNNodeKind.NONE : kind;
178: myRevision = revision == null ? SVNRevision.UNDEFINED
179: : revision;
180: myCommittedRevision = committedRevision == null ? SVNRevision.UNDEFINED
181: : committedRevision;
182: myCommittedDate = committedDate;
183: myAuthor = author;
184: myContentsStatus = contentsStatus == null ? SVNStatusType.STATUS_NONE
185: : contentsStatus;
186: myPropertiesStatus = propertiesStatus == null ? SVNStatusType.STATUS_NONE
187: : propertiesStatus;
188: myRemoteContentsStatus = remoteContentsStatus == null ? SVNStatusType.STATUS_NONE
189: : remoteContentsStatus;
190: myRemotePropertiesStatus = remotePropertiesStatus == null ? SVNStatusType.STATUS_NONE
191: : remotePropertiesStatus;
192: myIsLocked = isLocked;
193: myIsCopied = isCopied;
194: myIsSwitched = isSwitched;
195: myConflictNewFile = conflictNewFile;
196: myConflictOldFile = conflictOldFile;
197: myConflictWrkFile = conflictWrkFile;
198: myCopyFromURL = copyFromURL;
199: myCopyFromRevision = copyFromRevision == null ? SVNRevision.UNDEFINED
200: : copyFromRevision;
201: myRemoteLock = remoteLock;
202: myLocalLock = localLock;
203: myPropRejectFile = projRejectFile;
204: myEntryProperties = entryProperties;
205: }
206:
207: /**
208: * Gets the item's repository location. URL is taken from the
209: * {@link org.tmatesoft.svn.core.SVNProperty#URL} property.
210: *
211: * @return the item's URL represented as an <b>SVNURL</b> object
212: */
213: public SVNURL getURL() {
214: return myURL;
215: }
216:
217: /**
218: * Gets the item's latest repository location.
219: * For example, the item could have been moved in the repository,
220: * but {@link SVNStatus#getURL() getURL()} returns the item's
221: * URL as it's defined in a URL entry property. Applicable
222: * for a remote status invocation.
223: *
224: * @return the item's URL as it's real repository location
225: */
226: public SVNURL getRemoteURL() {
227: return myRemoteURL;
228: }
229:
230: /**
231: * Gets the item's path in the filesystem.
232: *
233: * @return a File representation of the item's path
234: */
235: public File getFile() {
236: return myFile;
237: }
238:
239: /**
240: * Gets the item's node kind characterizing it as an entry.
241: *
242: * @return the item's node kind (whether it's a file, directory, etc.)
243: */
244: public SVNNodeKind getKind() {
245: return myKind;
246: }
247:
248: /**
249: * Gets the item's current working revision.
250: *
251: * @return the item's working revision
252: */
253: public SVNRevision getRevision() {
254: return myRevision;
255: }
256:
257: /**
258: * Gets the revision when the item was last changed (committed).
259: *
260: * @return the last committed revision
261: */
262: public SVNRevision getCommittedRevision() {
263: return myCommittedRevision;
264: }
265:
266: /**
267: * Gets the timestamp when the item was last changed (committed).
268: *
269: * @return the last committed date
270: */
271: public Date getCommittedDate() {
272: return myCommittedDate;
273: }
274:
275: /**
276: * Gets the author who last changed the item.
277: *
278: * @return the item's last commit author
279: */
280: public String getAuthor() {
281: return myAuthor;
282: }
283:
284: /**
285: * Gets the Working Copy local item's contents status type.
286: *
287: * @return the local contents status type
288: */
289: public SVNStatusType getContentsStatus() {
290: return myContentsStatus;
291: }
292:
293: /**
294: * Gets the Working Copy local item's properties status type.
295: *
296: * @return the local properties status type
297: */
298: public SVNStatusType getPropertiesStatus() {
299: return myPropertiesStatus;
300: }
301:
302: /**
303: * Gets the Working Copy item's contents status type against the
304: * repository - that is comparing the item's BASE revision and the
305: * latest one in the repository when the item was changed.
306: * Applicable for a remote status invocation.
307: *
308: * <p>
309: * If the remote contents status type != {@link SVNStatusType#STATUS_NONE}
310: * the local file may be out of date.
311: *
312: * @return the remote contents status type
313: */
314: public SVNStatusType getRemoteContentsStatus() {
315: return myRemoteContentsStatus;
316: }
317:
318: /**
319: * Gets the Working Copy item's properties status type against the
320: * repository - that is comparing the item's BASE revision and the
321: * latest one in the repository when the item was changed. Applicable
322: * for a remote status invocation.
323: *
324: * <p>
325: * If the remote properties status type != {@link SVNStatusType#STATUS_NONE}
326: * the local file may be out of date.
327: *
328: * @return the remote properties status type
329: */
330: public SVNStatusType getRemotePropertiesStatus() {
331: return myRemotePropertiesStatus;
332: }
333:
334: /**
335: * Finds out if the item is locked (not a user lock but a driver's
336: * one when during an operation a Working Copy is locked in <i>.svn</i>
337: * administrative areas to prevent from other operations interrupting
338: * until the running one finishes).
339: * <p>
340: * To clean up a Working Copy use {@link SVNWCClient#doCleanup(File) doCleanup()}.
341: *
342: * @return <span class="javakeyword">true</span> if locked, otherwise
343: * <span class="javakeyword">false</span>
344: */
345: public boolean isLocked() {
346: return myIsLocked;
347: }
348:
349: /**
350: * Finds out if the item is added with history.
351: *
352: * @return <span class="javakeyword">true</span> if the item
353: * is added with history, otherwise <span class="javakeyword">false</span>
354: */
355: public boolean isCopied() {
356: return myIsCopied;
357: }
358:
359: /**
360: * Finds out whether the item is switched to a different
361: * repository location.
362: *
363: * @return <span class="javakeyword">true</span> if switched, otherwise
364: * <span class="javakeyword">false</span>
365: */
366: public boolean isSwitched() {
367: return myIsSwitched;
368: }
369:
370: /**
371: * Gets the temporary file that contains all latest changes from the
372: * repository which led to a conflict with local changes. This file is
373: * at the HEAD revision.
374: *
375: * @return an autogenerated temporary file just as it is in the latest
376: * revision in the repository
377: */
378: public File getConflictNewFile() {
379: return myConflictNewFile;
380: }
381:
382: /**
383: * Gets the temporary BASE revision file of that working file that is
384: * currently in conflict with changes received from the repository. This
385: * file does not contain the latest user's modifications, only 'pristine'
386: * contents.
387: *
388: * @return an autogenerated temporary file just as the conflicting file was
389: * before any modifications to it
390: */
391: public File getConflictOldFile() {
392: return myConflictOldFile;
393: }
394:
395: /**
396: * Gets the temporary <i>'.mine'</i> file with all current local changes to the
397: * original file. That is if the file item is in conflict with changes that
398: * came during an update this temporary file is created to get the snapshot
399: * of the user's file with only the user's local modifications and nothing
400: * more.
401: *
402: * @return an autogenerated temporary file with only the user's modifications
403: */
404: public File getConflictWrkFile() {
405: return myConflictWrkFile;
406: }
407:
408: /**
409: * Gets the <i>'.prej'</i> file containing details on properties conflicts.
410: * If the item's properties are in conflict with those that came
411: * during an update this file will contain a conflict description.
412: *
413: * @return the properties conflicts file
414: */
415: public File getPropRejectFile() {
416: return myPropRejectFile;
417: }
418:
419: /**
420: * Gets the URL (repository location) of the ancestor from which the
421: * item was copied. That is when the item is added with history.
422: *
423: * @return the item ancestor's URL
424: */
425: public String getCopyFromURL() {
426: return myCopyFromURL;
427: }
428:
429: /**
430: * Gets the revision of the item's ancestor
431: * from which the item was copied (the item is added
432: * with history).
433: *
434: * @return the ancestor's revision
435: */
436: public SVNRevision getCopyFromRevision() {
437: return myCopyFromRevision;
438: }
439:
440: /**
441: * Gets the file item's repository lock -
442: * applicable for a remote status invocation.
443: *
444: * @return file item's repository lock
445: */
446: public SVNLock getRemoteLock() {
447: return myRemoteLock;
448: }
449:
450: /**
451: * Gets the file item's local lock.
452: *
453: * @return file item's local lock
454: */
455: public SVNLock getLocalLock() {
456: return myLocalLock;
457: }
458:
459: /**
460: * Gets the item's SVN specific <i>'<entry'</i> properties.
461: * These properties' names start with
462: * {@link org.tmatesoft.svn.core.SVNProperty#SVN_ENTRY_PREFIX}.
463: *
464: * @return a Map which keys are names of SVN entry properties mapped
465: * against their values (both strings)
466: */
467: public Map getEntryProperties() {
468: return myEntryProperties;
469: }
470:
471: /**
472: * Gets the item's last committed repository revision. Relevant for a
473: * remote status invocation.
474: *
475: * @return the latest repository revision when the item was changed;
476: * <span class="javakeyword">null</span> if there are no incoming
477: * changes for this file or directory.
478: */
479: public SVNRevision getRemoteRevision() {
480: return myRemoteRevision;
481: }
482:
483: /**
484: * Returns the kind of the item got from the repository. Relevant for a
485: * remote status invocation.
486: *
487: * @return a remote item kind
488: */
489: public SVNNodeKind getRemoteKind() {
490: return myRemoteKind;
491: }
492:
493: /**
494: * Gets the item's last changed date. Relevant for a
495: * remote status invocation.
496: *
497: * @return a repository last changed date
498: */
499: public Date getRemoteDate() {
500: return myRemoteDate;
501: }
502:
503: /**
504: * Gets the item's last changed author. Relevant for a
505: * remote status invocation.
506: *
507: * @return a last commit author
508: */
509: public String getRemoteAuthor() {
510: return myRemoteAuthor;
511: }
512:
513: /**
514: * Returns the last modified local time of the file item.
515: * Irrelevant for directories (for directories returns <code>Date(0)</code>).
516: *
517: * @return last modified time of the file
518: */
519: public Date getWorkingContentsDate() {
520: if (myLocalContentsDate == null) {
521: if (getFile() != null && getKind() == SVNNodeKind.FILE) {
522: myLocalContentsDate = new Date(getFile().lastModified());
523: } else {
524: myLocalContentsDate = new Date(0);
525: }
526: }
527: return myLocalContentsDate;
528: }
529:
530: /**
531: * Returns the last modified local time of file or directory
532: * properties.
533: *
534: * @return last modified time of the item properties
535: */
536: public Date getWorkingPropertiesDate() {
537: if (myLocalPropertiesDate == null) {
538: File propFile = null;
539: if (getFile() != null && getKind() == SVNNodeKind.DIR) {
540: propFile = new File(getFile().getAbsoluteFile()
541: .getParentFile(), SVNFileUtil
542: .getAdminDirectoryName());
543: propFile = new File(propFile, "dir-props");
544: } else if (getFile() != null
545: && getKind() == SVNNodeKind.FILE) {
546: propFile = new File(getFile().getAbsoluteFile()
547: .getParentFile(), SVNFileUtil
548: .getAdminDirectoryName());
549: propFile = new File(propFile, "props/"
550: + getFile().getName() + ".svn-work");
551: }
552: myLocalPropertiesDate = propFile != null ? new Date(
553: propFile.lastModified()) : new Date(0);
554: }
555: return myLocalPropertiesDate;
556: }
557:
558: /**
559: * Marks the item as an external. This method is used by SVNKit internals
560: * and not intended for users (from an API point of view).
561: *
562: */
563: public void markExternal() {
564: myContentsStatus = SVNStatusType.STATUS_EXTERNAL;
565: }
566:
567: /**
568: * Sets the item's remote status. Used by SVNKit internals and not
569: * intended for users (from an API point of view).
570: *
571: * @param contents item's contents status type against the repository
572: * @param props item's properties status type against the repository
573: * @param lock item's lock in the repository
574: * @param kind item's node kind
575: */
576: public void setRemoteStatus(SVNStatusType contents,
577: SVNStatusType props, SVNLock lock, SVNNodeKind kind) {
578: if (contents == SVNStatusType.STATUS_ADDED
579: && myRemoteContentsStatus == SVNStatusType.STATUS_DELETED) {
580: contents = SVNStatusType.STATUS_REPLACED;
581: }
582: myRemoteContentsStatus = contents != null ? contents
583: : myRemoteContentsStatus;
584: myRemotePropertiesStatus = props != null ? props
585: : myRemotePropertiesStatus;
586: if (lock != null) {
587: myRemoteLock = lock;
588: }
589: if (kind != null) {
590: myRemoteKind = kind;
591: }
592: }
593:
594: /**
595: * Sets the item's remote status. Used by SVNKit internals and not
596: * intended for users (from an API point of view).
597: *
598: * @param url item's repository URL
599: * @param contents item's contents status type against the repository
600: * @param props item's properties status type against the repository
601: * @param lock item's lock in the repository
602: * @param kind item's node kind
603: * @param revision item's latest revision when it was last committed
604: * @param date last item's committed date
605: * @param author last item's committed author
606: */
607: public void setRemoteStatus(SVNURL url, SVNStatusType contents,
608: SVNStatusType props, SVNLock lock, SVNNodeKind kind,
609: SVNRevision revision, Date date, String author) {
610: setRemoteStatus(contents, props, lock, kind);
611: myRemoteURL = url;
612: myRemoteRevision = revision == null ? SVNRevision.UNDEFINED
613: : revision;
614: myRemoteDate = date;
615: myRemoteAuthor = author;
616: myRemoteKind = kind;
617: }
618:
619: /**
620: * Sets the item's contents status type. Used by SVNKit internals and not
621: * intended for users (from an API point of view).
622: *
623: * @param statusType status type of the item's contents
624: */
625: public void setContentsStatus(SVNStatusType statusType) {
626: myContentsStatus = statusType;
627: }
628:
629: /**
630: * Sets a WC entry for which this object is generated.
631: * Used in internals.
632: *
633: * @param entry a WC entry
634: */
635: public void setEntry(SVNEntry entry) {
636: myEntry = entry;
637: }
638:
639: /**
640: * Returns a WC entry for which this object is generated.
641: *
642: * @return a WC entry (if set)
643: */
644: public SVNEntry getEntry() {
645: return myEntry;
646: }
647: }
|