Esempio n. 1
0
        public void RefreshItem(GitItem item, SvnNodeKind nodeKind)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            RefreshPath(item.FullPath, nodeKind);

            IGitItemUpdate updateItem = (IGitItemUpdate)item;

            if (!updateItem.IsStatusClean())
            {
                // Ok, the status update did not refresh the item requesting to be refreshed
                // That means the item is not here or RefreshPath would have added it

                GitItem other;
                if (_map.TryGetValue(item.FullPath, out other) && other != item)
                {
                    updateItem.RefreshTo(other); // This item is no longer current; but we have the status anyway
                }
                else
                {
                    Debug.Assert(false, "RefreshPath did not deliver up to date information",
                                 "The RefreshPath public api promises delivering up to date data, but none was received");

                    updateItem.RefreshTo(item.Exists ? NoSccStatus.NotVersioned : NoSccStatus.NotExisting, SvnNodeKind.Unknown);
                }
            }

            Debug.Assert(updateItem.IsStatusClean(), "The item requesting to be updated is updated");
        }
Esempio n. 2
0
        private void StatDirectory(string walkPath, GitDirectory directory, bool noWcAtAll)
        {
            // Note: There is a lock(_lock) around this in our caller

            bool        canRead;
            string      adminName   = GitClient.AdministrativeDirectoryName;
            NoSccStatus noSccStatus = noWcAtAll ? NoSccStatus.NotVersionable : NoSccStatus.NotVersioned;

            foreach (SccFileSystemNode node in SccFileSystemNode.GetDirectoryNodes(walkPath, out canRead))
            {
                if (string.Equals(node.Name, adminName, StringComparison.OrdinalIgnoreCase) || node.IsHiddenOrSystem)
                {
                    continue;
                }

                GitItem item;
                if (node.IsFile)
                {
                    if (!_map.TryGetValue(node.FullPath, out item))
                    {
                        StoreItem(CreateItem(node.FullPath, noSccStatus, SvnNodeKind.File));
                    }
                    else
                    {
                        IGitItemUpdate updateItem = item;
                        if (updateItem.ShouldRefresh())
                        {
                            updateItem.RefreshTo(noSccStatus, SvnNodeKind.File);
                        }
                    }
                }
                else
                {
                    if (!_map.TryGetValue(node.FullPath, out item))
                    {
                        StoreItem(CreateItem(node.FullPath, noSccStatus, SvnNodeKind.Directory));
                    }
                    // Don't clear state of a possible working copy
                }
            }

            if (canRead) // The directory exists
            {
                GitItem item;

                if (!_map.TryGetValue(walkPath, out item))
                {
                    StoreItem(CreateItem(walkPath, NoSccStatus.NotVersioned, SvnNodeKind.Directory));
                    // Mark it as existing if we are sure
                }
                else
                {
                    IGitItemUpdate updateItem = item;
                    if (updateItem.ShouldRefresh())
                    {
                        updateItem.RefreshTo(NoSccStatus.NotVersioned, SvnNodeKind.Directory);
                    }
                }
            }

            // Note: There is a lock(_lock) around this in our caller
        }
Esempio n. 3
0
        /// <summary>
        /// Refreshes the specified path using the specified depth
        /// </summary>
        /// <param name="path">A normalized path</param>
        /// <param name="pathKind"></param>
        /// <param name="depth"></param>
        /// <remarks>
        /// If the path is a file and depth is greater that <see cref="GitDepth.Empty"/> the parent folder is walked instead.
        ///
        /// <para>This method guarantees that after calling it at least one up-to-date item exists
        /// in the statusmap for <paramref name="path"/>. If we can not find information we create
        /// an unspecified item
        /// </para>
        /// </remarks>
        void RefreshPath(string path, SvnNodeKind pathKind)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }

            string walkPath         = path;
            bool   walkingDirectory = false;

            switch (pathKind)
            {
            case SvnNodeKind.Directory:
                walkingDirectory = true;
                break;

            case SvnNodeKind.File:
                walkPath         = SvnTools.GetNormalizedDirectoryName(path);
                walkingDirectory = true;
                break;

            default:
                try
                {
                    if (File.Exists(path))     // ### Not long path safe
                    {
                        pathKind = SvnNodeKind.File;
                        goto case SvnNodeKind.File;
                    }
                }
                catch (PathTooLongException)
                { /* Fall through */ }
                break;
            }

            GitStatusArgs args = new GitStatusArgs();

            args.IncludeUnversioned = true;
            args.IncludeUnmodified  = true;
            args.IncludeIgnored     = true;
            //args.IncludeDirectories = true;
            args.IncludeSubmodules     = true;
            args.GenerateVersionedDirs = true;

            lock (_lock)
            {
                GitDirectory        directory;
                IGitDirectoryUpdate updateDir;
                GitItem             walkItem;

                // We get more information for free, lets use that to update other items
                if (_dirMap.TryGetValue(walkPath, out directory))
                {
                    updateDir = directory;
                    updateDir.TickAll();
                }
                else
                {
                    // No existing directory instance, let's create one
                    updateDir         = directory = new GitDirectory(Context, walkPath);
                    _dirMap[walkPath] = directory;
                }

                walkItem = directory.Directory;

                bool     ok;
                bool     statSelf  = false;
                bool     noWcAtAll = false;
                string[] root;

                // Don't retry file open/read operations on failure. These would only delay the result
                // (default number of delays = 100)
                //using (new SharpGit.Implementation.GitFsOperationRetryOverride(0))
                try
                {
                    _root = null;
                    ok    = _client.Status(walkPath, args, RefreshCallback);
                }
                catch
                { ok = false; }
                finally
                {
                    root = _root;
                }

                if (!ok)
                {
                    statSelf = true;
                }
                else if (directory != null)
                {
                    walkItem = directory.Directory; // Might have changed via casing
                }
                if (!statSelf)
                {
                    if (((IGitItemUpdate)walkItem).ShouldRefresh())
                    {
                        statSelf = true;
                    }
                    else if (walkingDirectory && !walkItem.IsVersioned)
                    {
                        statSelf = true;
                    }
                }

                if (statSelf)
                {
                    // Git did not stat the items for us.. Let's make something up

                    if (walkingDirectory)
                    {
                        StatDirectory(walkPath, directory, noWcAtAll);
                    }
                    else
                    {
                        // Just stat the item passed and nothing else in the Depth.Empty case

                        if (walkItem == null)
                        {
                            string truepath = SvnTools.GetTruePath(walkPath); // Gets the on-disk casing if it exists

                            StoreItem(walkItem = CreateItem(truepath ?? walkPath,
                                                            (truepath != null) ? NoSccStatus.NotVersioned : NoSccStatus.NotExisting, SvnNodeKind.Unknown));
                        }
                        else
                        {
                            ((IGitItemUpdate)walkItem).RefreshTo(walkItem.Exists ? NoSccStatus.NotVersioned : NoSccStatus.NotExisting, SvnNodeKind.Unknown);
                        }
                    }
                }

                if (directory != null)
                {
                    foreach (IGitItemUpdate item in directory)
                    {
                        if (item.IsItemTicked()) // These items were not found in the stat calls
                        {
                            item.RefreshTo(NoSccStatus.NotExisting, SvnNodeKind.Unknown);
                        }
                    }

                    if (updateDir.ScheduleForCleanup)
                    {
                        ScheduleForCleanup(directory); // Handles removing already deleted items
                    }
                    // We keep them cached for the current command only
                }


                GitItem pathItem; // We promissed to return an updated item for the specified path; check if we updated it

                if (!_map.TryGetValue(path, out pathItem))
                {
                    // We did not; it does not even exist in the cache
                    StoreItem(pathItem = CreateItem(path, NoSccStatus.NotExisting));

                    if (directory != null)
                    {
                        updateDir.Store(pathItem);
                        ScheduleForCleanup(directory);
                    }
                }
                else
                {
                    IGitItemUpdate update = pathItem;

                    if (!update.IsStatusClean())
                    {
                        update.RefreshTo(NoSccStatus.NotExisting, SvnNodeKind.Unknown); // We did not see it in the walker

                        if (directory != null)
                        {
                            ((IGitDirectoryUpdate)directory).Store(pathItem);
                            ScheduleForCleanup(directory);
                        }
                    }
                }
            }
        }