예제 #1
0
        void SetState(SvnItemState set, SvnItemState unset)
        {
            // NOTE: This method is /not/ thread safe, but its callers have race conditions anyway
            // Setting an integer could worst case completely destroy the integer; nothing a refresh can't fix

            var st = (_currentState & ~unset) | set;

            if (st != _currentState)
            {
                // Calculate whether we have a change or just new information
                var changed = (st & _onceValid & _noBroadcastFor) != (_currentState & _onceValid & _noBroadcastFor);

                if (changed && !_enqueued)
                {
                    _enqueued = true;

                    // Schedule a stat changed broadcast
                    lock (_stateChanged)
                    {
                        _stateChanged.Enqueue(this);

                        ScheduleUpdateNotify();
                    }
                }

                _currentState = st;
            }
            _validState |= (set | unset);
            _onceValid  |= _validState;
        }
예제 #2
0
        private void SetDirty(SvnItemState dirty)
        {
            // NOTE: This method is /not/ thread safe, but its callers have race conditions anyway
            // Setting an integer could worst case completely destroy the integer; nothing a refresh can't fix

            _validState &= ~dirty;
        }
예제 #3
0
        bool TryGetState(SvnItemState mask, out SvnItemState result)
        {
            if ((mask & _validState) != mask)
            {
                result = SvnItemState.None;
                return(false);
            }

            result = _currentState & mask;
            return(true);
        }
예제 #4
0
        void UpdateMustLock()
        {
            SvnItemState fastValue = SvnItemState.IsDiskFile | SvnItemState.ReadOnly;
            SvnItemState slowValue = SvnItemState.Versioned;
            SvnItemState v;

            bool mustLock;

            if (TryGetState(SvnItemState.Versioned, out v) && (v == 0))
            {
                mustLock = false;
            }
            else if (TryGetState(SvnItemState.HasProperties, out v) && (v == 0))
            {
                mustLock = false;
            }
            else if (TryGetState(SvnItemState.ReadOnly, out v) && (v == 0))
            {
                mustLock = false;
            }
            else if (GetState(fastValue) != fastValue)
            {
                mustLock = false;
            }
            else if (GetState(slowValue) != slowValue)
            {
                mustLock = false;
            }
            else
            {
                using (SvnClient client = _context.GetService <ISvnClientPool>().GetNoUIClient())
                {
                    string propVal;

                    if (client.TryGetProperty(FullPath, SvnPropertyNames.SvnNeedsLock, out propVal))
                    {
                        mustLock = propVal != null; // Value should be equal to SvnPropertyNames.SvnBooleanValue
                    }
                    else
                    {
                        mustLock = false;
                    }
                }
            }

            if (mustLock)
            {
                SetState(SvnItemState.MustLock, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.MustLock);
            }
        }
예제 #5
0
        void UpdateTextFile()
        {
            SvnItemState value = SvnItemState.IsDiskFile | SvnItemState.Versioned;
            SvnItemState v;

            bool isTextFile;

            if (TryGetState(SvnItemState.Versioned, out v) && (v == 0))
            {
                isTextFile = false;
            }
            else if (GetState(value) != value)
            {
                isTextFile = false;
            }
            else
            {
                using (SvnWorkingCopyClient client = _context.GetService <ISvnClientPool>().GetWcClient())
                {
                    SvnWorkingCopyStateArgs a = new SvnWorkingCopyStateArgs();
                    a.ThrowOnError     = false;
                    a.RetrieveFileData = true;
                    SvnWorkingCopyState state;
                    if (client.GetState(FullPath, out state))
                    {
                        isTextFile = state.IsTextFile;
                    }
                    else
                    {
                        isTextFile = false;
                    }
                }
            }

            if (isTextFile)
            {
                SetState(SvnItemState.IsTextFile, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.IsTextFile);
            }
        }
예제 #6
0
        void UpdateAttributeInfo()
        {
            // One call of the kernel's GetFileAttributesW() gives us most info we need

            uint value = NativeMethods.GetFileAttributes(FullPath);

            if (value == NativeMethods.INVALID_FILE_ATTRIBUTES)
            {
                // File does not exist / no rights, etc.

                SetState(SvnItemState.None,
                         SvnItemState.Exists | SvnItemState.ReadOnly | SvnItemState.MustLock | SvnItemState.Versionable | SvnItemState.IsDiskFolder | SvnItemState.IsDiskFile);

                return;
            }

            SvnItemState set   = SvnItemState.Exists;
            SvnItemState unset = SvnItemState.None;

            if ((value & NativeMethods.FILE_ATTRIBUTE_READONLY) != 0)
            {
                set |= SvnItemState.ReadOnly;
            }
            else
            {
                unset = SvnItemState.ReadOnly;
            }

            if ((value & NativeMethods.FILE_ATTRIBUTE_DIRECTORY) != 0)
            {
                unset |= SvnItemState.IsDiskFile | SvnItemState.ReadOnly;
                set    = SvnItemState.IsDiskFolder | (set & ~SvnItemState.ReadOnly); // Don't set readonly
            }
            else
            {
                set   |= SvnItemState.IsDiskFile;
                unset |= SvnItemState.IsDiskFolder;
            }

            SetState(set, unset);
        }
예제 #7
0
        /// <summary>
        /// Copies all information from other.
        /// </summary>
        /// <param name="lead"></param>
        /// <remarks>When this method is called the other item will eventually replace this item</remarks>
        void ISvnItemUpdate.RefreshTo(SvnItem lead)
        {
            if (lead == null)
            {
                throw new ArgumentNullException("lead");
            }
            else if (lead._status == null)
            {
                throw new InvalidOperationException("Lead status = null");
            }

            _status      = lead._status;
            _statusDirty = lead._statusDirty;

            SvnItemState current = lead._currentState;
            SvnItemState valid   = lead._validState;

            SetState(current & valid, (~current) & valid);
            _ticked   = false;
            _modified = lead._modified;
            _cookie   = NextCookie(); // Status 100% the same, but changed... Cookies are free ;)
        }
예제 #8
0
        void RefreshTo(NoSccStatus status, SvnNodeKind nodeKind)
        {
            _cookie      = NextCookie();
            _statusDirty = XBool.False;

            SvnItemState set   = SvnItemState.None;
            SvnItemState unset = SvnItemState.Modified | SvnItemState.Added | SvnItemState.HasCopyOrigin
                                 | SvnItemState.Deleted | SvnItemState.ContentConflicted | SvnItemState.Ignored
                                 | SvnItemState.Obstructed | SvnItemState.Replaced | SvnItemState.Versioned
                                 | SvnItemState.SvnDirty | SvnItemState.PropertyModified | SvnItemState.PropertiesConflicted | SvnItemState.Conflicted
                                 | SvnItemState.Obstructed | SvnItemState.MustLock | SvnItemState.IsWCRoot
                                 | SvnItemState.HasProperties | SvnItemState.HasLockToken | SvnItemState.HasCopyOrigin
                                 | SvnItemState.MovedHere;

            switch (status)
            {
            case NoSccStatus.NotExisting:
                SetState(set, SvnItemState.Exists | SvnItemState.ReadOnly | SvnItemState.IsDiskFile | SvnItemState.IsDiskFolder | SvnItemState.Versionable | unset);
                _status = SvnStatusData.NotExisting;
                break;

            case NoSccStatus.NotVersionable:
                unset |= SvnItemState.Versionable;
                goto case NoSccStatus.NotVersioned;     // fall through

            case NoSccStatus.NotVersioned:
                SetState(SvnItemState.Exists | set, SvnItemState.None | unset);
                _status = SvnStatusData.NotVersioned;
                break;

            case NoSccStatus.Unknown:
            default:
                SetDirty(set | unset);
                _statusDirty = XBool.True;
                break;
            }

            InitializeFromKind(nodeKind);
        }
예제 #9
0
        void RefreshTo(SvnStatusData status)
        {
            if (status == null)
            {
                throw new ArgumentNullException("status");
            }

            if (status.LocalNodeStatus == SvnStatus.External)
            {
                // When iterating the status of an external in it's parent directory
                // We get an external status and no really usefull information

                SetState(SvnItemState.Exists | SvnItemState.Versionable | SvnItemState.IsDiskFolder,
                         SvnItemState.IsDiskFile | SvnItemState.ReadOnly | SvnItemState.MustLock | SvnItemState.IsTextFile);

                if (_statusDirty != XBool.False)
                {
                    _statusDirty = XBool.True; // Walk the path itself to get the data you want
                }
                return;
            }
            else if (MightBeNestedWorkingCopy(status) && IsDirectory)
            {
                // A not versioned directory might be a working copy by itself!

                if (_statusDirty == XBool.False)
                {
                    return; // No need to remove valid cache entries
                }
                if (SvnTools.IsManagedPath(FullPath))
                {
                    _statusDirty = XBool.True; // Walk the path itself to get the data

                    // Extract useful information we got anyway

                    SetState(SvnItemState.Exists | SvnItemState.Versionable | SvnItemState.Versioned | SvnItemState.IsWCRoot | SvnItemState.IsDiskFolder,
                             SvnItemState.IsDiskFile | SvnItemState.ReadOnly | SvnItemState.MustLock | SvnItemState.IsTextFile);

                    return;
                }
                else
                {
                    SetState(SvnItemState.None, SvnItemState.IsWCRoot);
                }
                // Fall through
            }

            _cookie      = NextCookie();
            _statusDirty = XBool.False;
            _status      = status;

            const SvnItemState unset = SvnItemState.Modified | SvnItemState.Added |
                                       SvnItemState.HasCopyOrigin | SvnItemState.Deleted | SvnItemState.ContentConflicted |
                                       SvnItemState.Ignored | SvnItemState.Obstructed | SvnItemState.Replaced |
                                       SvnItemState.MovedHere;

            const SvnItemState managed = SvnItemState.Versioned;


            // Let's assume status is more recent than our internal property cache
            // Set all caching properties we can

            bool svnDirty        = true;
            bool exists          = true;
            bool provideDiskInfo = true;

            switch (status.LocalNodeStatus)
            {
            case SvnStatus.None:
                SetState(SvnItemState.None, managed | unset);
                svnDirty        = false;
                exists          = false;
                provideDiskInfo = false;
                break;

            case SvnStatus.NotVersioned:
                // Node exists but is not managed by us in this directory
                // (Might be from an other location as in the nested case)
                SetState(SvnItemState.None, unset | managed);
                svnDirty = false;
                break;

            case SvnStatus.Ignored:
                // Node exists but is not managed by us in this directory
                // (Might be from an other location as in the nested case)
                SetState(SvnItemState.Ignored, unset | managed);
                svnDirty = false;
                break;

            case SvnStatus.Added:
                if (status.IsMoved && status.IsCopied)
                {
                    SetState(managed | SvnItemState.Added | SvnItemState.HasCopyOrigin | SvnItemState.MovedHere, unset);
                }
                else if (status.IsCopied)
                {
                    SetState(managed | SvnItemState.Added | SvnItemState.HasCopyOrigin, unset);
                }
                else
                {
                    SetState(managed | SvnItemState.Added, unset);
                }

                if (status.LocalTextStatus == SvnStatus.Modified)
                {
                    SetState(SvnItemState.Modified, SvnItemState.None);
                }
                else if (status.LocalTextStatus == SvnStatus.Normal)
                {
                    SetState(SvnItemState.None, SvnItemState.Modified);
                }
                break;

            case SvnStatus.Replaced:
                if (status.IsMoved && status.IsCopied)
                {
                    SetState(managed | SvnItemState.Replaced | SvnItemState.HasCopyOrigin | SvnItemState.MovedHere, unset);
                }
                else if (status.IsCopied)
                {
                    SetState(managed | SvnItemState.Replaced | SvnItemState.HasCopyOrigin, unset);
                }
                else
                {
                    SetState(managed | SvnItemState.Replaced, unset);
                }

                if (status.LocalTextStatus == SvnStatus.Modified)
                {
                    SetState(SvnItemState.Modified, SvnItemState.None);
                }
                else if (status.LocalTextStatus == SvnStatus.Normal)
                {
                    SetState(SvnItemState.None, SvnItemState.Modified);
                }
                break;

            case SvnStatus.Modified:
            case SvnStatus.Conflicted:
            {
                bool done = false;
                switch (status.LocalTextStatus)
                {
                case SvnStatus.Modified:
                    SetState(managed | SvnItemState.Modified, unset);
                    done = true;
                    break;

                case SvnStatus.Conflicted:
                    SetState(managed | SvnItemState.ContentConflicted | SvnItemState.Conflicted, unset);
                    done = true;
                    break;
                }
                if (!done)
                {
                    goto case SvnStatus.Normal;
                }
                break;
            }

            case SvnStatus.Obstructed:     // node exists but is of the wrong type
                SetState(SvnItemState.None, managed | unset);
                provideDiskInfo = false;   // Info is wrong
                break;

            case SvnStatus.Missing:
                exists          = false;
                provideDiskInfo = false;     // Info is wrong
                SetState(managed, unset);
                break;

            case SvnStatus.Deleted:
                SetState(managed | SvnItemState.Deleted, unset);
                if (status.LocalFileExists)
                {
                    exists = provideDiskInfo = true;
                }
                else
                {
                    exists          = false;
                    provideDiskInfo = false;     // Folder might still exist
                }
                break;

            case SvnStatus.External:
                // Should be handled above
                throw new InvalidOperationException();

            case SvnStatus.Incomplete:
                SetState(managed, unset);
                break;

            default:
                Trace.WriteLine(string.Format("Ignoring undefined status {0} in SvnItem.Refresh()", status.LocalNodeStatus));
                provideDiskInfo = false;     // Can't trust an unknown status
                goto case SvnStatus.Normal;

            case SvnStatus.Normal:
                SetState(managed | SvnItemState.Exists, unset);
                svnDirty = false;
                break;
            }

            if (exists)
            {
                SetState(SvnItemState.Versionable, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.Versionable);
            }

            if (status.Conflicted)
            {
                SetState(SvnItemState.Conflicted, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.Conflicted);
            }


            bool hasProperties = true;

            switch (status.LocalPropertyStatus)
            {
            case SvnStatus.None:
                hasProperties = false;
                SetState(SvnItemState.None, SvnItemState.PropertiesConflicted | SvnItemState.PropertyModified | SvnItemState.HasProperties);
                break;

            case SvnStatus.Modified:
                SetState(SvnItemState.PropertyModified | SvnItemState.HasProperties,
                         SvnItemState.PropertiesConflicted);
                svnDirty = true;
                break;

            case SvnStatus.Conflicted:
                SetState(SvnItemState.PropertyModified | SvnItemState.PropertiesConflicted | SvnItemState.HasProperties,
                         SvnItemState.None);
                svnDirty = true;
                break;

            case SvnStatus.Normal:
            default:
                SetState(SvnItemState.HasProperties,
                         SvnItemState.PropertiesConflicted | SvnItemState.PropertyModified);
                break;
            }

            if (svnDirty)
            {
                SetState(SvnItemState.SvnDirty, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.SvnDirty);
            }

            if (!hasProperties)
            {
                SetState(SvnItemState.None, SvnItemState.MustLock);
            }

            if (provideDiskInfo)
            {
                if (exists) // Behaviour must match updating from UpdateAttributeInfo()
                {
                    switch (status.NodeKind)
                    {
                    case SvnNodeKind.Directory:
                        SetState(SvnItemState.IsDiskFolder | SvnItemState.Exists, SvnItemState.ReadOnly | SvnItemState.MustLock | SvnItemState.IsTextFile | SvnItemState.IsDiskFile);
                        break;

                    case SvnNodeKind.File:
                        SetState(SvnItemState.IsDiskFile | SvnItemState.Exists, SvnItemState.IsDiskFolder);
                        break;

                    default:
                        // Handle direct replacement without an additional stat
                        if (status.LocalFileExists)
                        {
                            goto case SvnNodeKind.File;
                        }
                        break;
                    }
                }
                else
                {
                    SetState(SvnItemState.None, SvnItemState.Exists);
                }
            }

            if (status.IsLockedLocal)
            {
                SetState(SvnItemState.HasLockToken, SvnItemState.None);
            }
            else
            {
                SetState(SvnItemState.None, SvnItemState.HasLockToken);
            }
        }
예제 #10
0
        public SvnItemState GetState(SvnItemState flagsToGet)
        {
            var unavailable = flagsToGet & ~_validState;

            if (unavailable == 0)
            {
                return(_currentState & flagsToGet); // We have everything we need
            }
            if (0 != (unavailable & _maskRefreshTo))
            {
                Debug.Assert(_statusDirty != XBool.False);
                RefreshStatus();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskRefreshTo) == 0, "RefreshMe() set all attributes it should");
            }

            if (0 != (unavailable & _maskGetAttributes))
            {
                UpdateAttributeInfo();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskGetAttributes) == 0, "UpdateAttributeInfo() set all attributes it should");
            }

            if (0 != (unavailable & _maskUpdateSolution))
            {
                UpdateSolutionInfo();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskUpdateSolution) == 0, "UpdateSolution() set all attributes it should");
            }

            if (0 != (unavailable & _maskDocumentInfo))
            {
                UpdateDocumentInfo();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskDocumentInfo) == 0, "UpdateDocumentInfo() set all attributes it should");
            }

            if (0 != (unavailable & _maskVersionable))
            {
                UpdateVersionable();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskVersionable) == 0, "UpdateVersionable() set all attributes it should");
            }

            if (0 != (unavailable & _maskMustLock))
            {
                UpdateMustLock();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskMustLock) == 0, "UpdateMustLock() set all attributes it should");
            }

            if (0 != (unavailable & _maskTextFile))
            {
                UpdateTextFile();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskTextFile) == 0, "UpdateTextFile() set all attributes it should");
            }

            if (0 != (unavailable & _maskWCRoot))
            {
                UpdateWCRoot();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskWCRoot) == 0, "UpdateWCRoot() set all attributes it should");
            }

            if (0 != (unavailable & _maskIsAdministrativeArea))
            {
                UpdateAdministrativeArea();

                unavailable = flagsToGet & ~_validState;

                Debug.Assert((~_validState & _maskIsAdministrativeArea) == 0, "UpdateIsAdministrativeArea() set all attributes it should");
            }

            if (unavailable != 0)
            {
                Trace.WriteLine(string.Format("Don't know how to retrieve {0:X} state; clearing dirty flag", (int)unavailable));

                _validState |= unavailable;
            }

            return(_currentState & flagsToGet);
        }
예제 #11
0
 bool ISvnItemUpdate.TryGetState(SvnItemState get, out SvnItemState value)
 {
     return(TryGetState(get, out value));
 }
예제 #12
0
 void ISvnItemUpdate.SetDirty(SvnItemState dirty)
 {
     SetDirty(dirty);
 }
예제 #13
0
 void ISvnItemUpdate.SetState(SvnItemState set, SvnItemState unset)
 {
     SetState(set, unset);
 }