internal void CopyState(SccDocumentData data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            _initialUpdateCompleted = data._initialUpdateCompleted;
            _isDirty = data._isDirty;
            _itemId = data._itemId;
            _hierarchy = data._hierarchy;
        }
        /// <summary>
        /// Gets the parent document of a document (normally a project or the solution)
        /// </summary>
        /// <param name="document">The document.</param>
        /// <returns></returns>
        internal string GetParentDocument(SccDocumentData document)
        {
            IVsHierarchy hier = document.Hierarchy;

            foreach (SccDocumentData dd in _docMap.Values)
            {
                IVsHierarchy hh = dd.RawDocument as IVsHierarchy;

                if (hh != null && dd.Hierarchy == hier)
                {
                    return dd.Name;
                }
            }

            return null;
        }
        public int OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
        {
            SccDocumentData data;
            if (!TryGetDocument(docCookie, true, out data))
                return VSConstants.S_OK;

            data.OnAttributeChange((__VSRDTATTRIB)grfAttribs);

            if (!string.IsNullOrEmpty(pszMkDocumentNew) && pszMkDocumentNew != pszMkDocumentOld)
            {
                // The document changed names; for SCC this is a close without saving and setting dirty state on new document

                SccDocumentData newData;

                if (!_docMap.TryGetValue(pszMkDocumentNew, out newData))
                    _docMap.Add(pszMkDocumentNew, newData = new SccDocumentData(Context, pszMkDocumentNew));
                else if (newData.Cookie != 0)
                {
                    _cookieMap.Remove(newData.Cookie);
                    newData.Cookie = 0;
                }

                if (data != null)
                {
                    newData.CopyState(data);

                    newData.Cookie = data.Cookie;
                    _cookieMap[newData.Cookie] = newData;
                    data.Cookie = 0;

                    data.Dispose();
                }

                data = newData;
            }

            if (pHierNew != null)
                data.Hierarchy = pHierNew;
            if (itemidNew != VSConstants.VSITEMID_NIL)
                data.ItemId = itemidNew;

            if (!string.IsNullOrEmpty(pszMkDocumentNew) && !string.IsNullOrEmpty(pszMkDocumentOld)
                && pszMkDocumentNew != pszMkDocumentOld)
            {
                if (GitItem.IsValidPath(pszMkDocumentNew) && GitItem.IsValidPath(pszMkDocumentOld))
                {
                    string oldFile = GitTools.GetNormalizedFullPath(pszMkDocumentOld);
                    string newFile = GitTools.GetNormalizedFullPath(pszMkDocumentNew);
                    ProjectTracker.OnDocumentSaveAs(oldFile, newFile);
                    SccProvider.OnDocumentSaveAs(oldFile, newFile);
                }
            }

            return VSConstants.S_OK;
        }
        bool TryGetDocument(uint cookie, bool forUpdate, out SccDocumentData data)
        {
            if (cookie == 0)
            {
                data = null;
                return false;
            }

            if (_cookieMap.TryGetValue(cookie, out data))
                return true;

            uint flags;
            uint locks;
            uint editLocks;
            string name;
            IVsHierarchy hier;
            uint itemId;
            IntPtr ppunkDocData;

            if (ErrorHandler.Succeeded(RunningDocumentTable.GetDocumentInfo(cookie,
                out flags, out locks, out editLocks, out name, out hier, out itemId, out ppunkDocData)))
            {
                object document = null;

                if (ppunkDocData != IntPtr.Zero)
                {
                    document = Marshal.GetUniqueObjectForIUnknown(ppunkDocData);
                    Marshal.Release(ppunkDocData);
                }

                if (!string.IsNullOrEmpty(name))
                {
                    if (_docMap.TryGetValue(name, out data))
                    {
                        if (data.Cookie != 0)
                        {
                            _cookieMap.Remove(data.Cookie);
                            data.Cookie = 0;
                        }

                        if (!forUpdate)
                        {
                            Debug.Assert(data.Hierarchy == hier, "Hierarchy not the same", string.Format("File={0}", data.Name));
                            Debug.Assert(data.ItemId == itemId, "Id not the same", string.Format("File={0}; from {1} into {2}", data.Name, data.ItemId, itemId));
                        }
                    }
                    else
                    {
                        _docMap.Add(name, data = new SccDocumentData(Context, name));
                        data.Hierarchy = hier;
                        data.ItemId = itemId;
                    }

                    if (document != null)
                        data.RawDocument = document;

                    data.Cookie = cookie;
                    _cookieMap.Add(cookie, data);
                }
            }
            else
                data = null;

            return (data != null);
        }
 bool TryGetDocument(uint cookie, out SccDocumentData data)
 {
     return TryGetDocument(cookie, false, out data);
 }
        internal void DoDispose(SccDocumentData data)
        {
            if (data == null)
                throw new ArgumentNullException("data");

            Debug.Assert(_docMap[data.Name] == data);

            _docMap.Remove(data.Name);

            if (data.Cookie != 0)
            {
                Debug.Assert(_cookieMap[data.Cookie] == data);

                _cookieMap.Remove(data.Cookie);
                data.Cookie = 0;
            }
        }
        /// <summary>
        /// Called before a document is locked in the Running Document Table (RDT) for the first time.
        /// </summary>
        /// <param name="pHier">[in] The <see cref="T:Microsoft.VisualStudio.Shell.Interop.IVsHierarchy"></see> object that owns the document about to be locked.</param>
        /// <param name="itemid">[in] The item ID in the hierarchy. This is a unique identifier or it can be one of the following values: <see cref="F:Microsoft.VisualStudio.VSConstants.VSITEMID_NIL"></see>, <see cref="F:Microsoft.VisualStudio.VSConstants.VSITEMID_ROOT"></see>, or <see cref="F:Microsoft.VisualStudio.VSConstants.VSITEMID_SELECTION"></see>.</param>
        /// <param name="pszMkDocument">[in] The path to the document about to be locked.</param>
        /// <returns>
        /// If the method succeeds, it returns <see cref="F:Microsoft.VisualStudio.VSConstants.S_OK"></see>. If it fails, it returns an error code.
        /// </returns>
        public int OnBeforeFirstDocumentLock(IVsHierarchy pHier, uint itemid, string pszMkDocument)
        {
            if (string.IsNullOrEmpty(pszMkDocument))
            {
                return VSConstants.S_OK; // Can't be a valid path; don't monitor
            }

            SccDocumentData data;
            if (!_docMap.TryGetValue(pszMkDocument, out data))
            {
                _docMap.Add(pszMkDocument, data = new SccDocumentData(Context, pszMkDocument));

                data.Hierarchy = pHier;
                data.ItemId = itemid;
            }

            return VSConstants.S_OK;
        }