private Addition CanAddFileFromProjectReference()

in Nodejs/Product/Nodejs/SharedProject/ProjectNode.CopyPaste.cs [1007:1231]


            private Addition CanAddFileFromProjectReference(string projectRef, string targetFolder, bool fromFolder = false)
            {
                Utilities.ArgumentNotNullOrEmpty(nameof(projectRef), projectRef);

                var solution = this.Project.GetService(typeof(IVsSolution)) as IVsSolution;
                Utilities.CheckNotNull(solution);
                var reason = new VSUPDATEPROJREFREASON[1];
                if (ErrorHandler.Failed(solution.GetItemOfProjref(projectRef, out var hierarchy, out var itemidLoc, out var str, reason)))
                {
                    GetPathAndProjectId(projectRef, out var projectGuid, out var path);
                    ReportMissingItem(path);
                    return null;
                }

                Utilities.CheckNotNull(hierarchy);

                // This will throw invalid cast exception if the hierrachy is not a project.
                var project = (IVsProject)hierarchy;
                var isLink = false;
                if (ErrorHandler.Succeeded(((IVsHierarchy)project).GetProperty(itemidLoc, (int)__VSHPROPID2.VSHPROPID_IsLinkFile, out var isLinkValue)))
                {
                    if (isLinkValue is bool)
                    {
                        isLink = (bool)isLinkValue;
                    }
                }

                ErrorHandler.ThrowOnFailure(project.GetMkDocument(itemidLoc, out var moniker));

                if (this.DropEffect == DropEffect.Move && IsBadMove(targetFolder, moniker, true))
                {
                    return null;
                }

                if (!File.Exists(moniker))
                {
                    Utilities.ShowMessageBox(
                            this.Project.Site,
                            string.Format("The item '{0}' does not exist in the project directory. It may have been moved, renamed or deleted.", Path.GetFileName(moniker)),
                            null,
                            OLEMSGICON.OLEMSGICON_CRITICAL,
                            OLEMSGBUTTON.OLEMSGBUTTON_OK,
                            OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    return null;
                }

                // Check that the source and destination paths aren't the same since we can't move an item to itself.
                // If they are in fact the same location, throw an error that copy/move will not work correctly.
                if (this.DropEffect == DropEffect.Move && !CommonUtils.IsSamePath(Path.GetDirectoryName(moniker), Path.GetDirectoryName(targetFolder)))
                {
                    try
                    {
                        var sourceLinkTarget = NativeMethods.GetAbsolutePathToDirectory(Path.GetDirectoryName(moniker));
                        string destinationLinkTarget = null;

                        // if the directory doesn't exist, just skip this.  We will create it later.
                        if (Directory.Exists(targetFolder))
                        {
                            try
                            {
                                destinationLinkTarget = NativeMethods.GetAbsolutePathToDirectory(targetFolder);
                            }
                            catch (FileNotFoundException)
                            {
                                // This can occur if the user had a symlink'd directory and deleted the backing directory.
                                Utilities.ShowMessageBox(
                                            this.Project.Site,
                                            string.Format(
                                                "Unable to find the destination folder."),
                                            null,
                                            OLEMSGICON.OLEMSGICON_CRITICAL,
                                            OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                            OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                                return null;
                            }
                        }

                        // If the paths are the same, we can't really move the file...
                        if (destinationLinkTarget != null && CommonUtils.IsSamePath(sourceLinkTarget, destinationLinkTarget))
                        {
                            CannotMoveSameLocation(moniker);
                            return null;
                        }
                    }
                    catch (Exception ex) when (!ExceptionExtensions.IsCriticalException(ex))
                    {
                        return null;
                    }
                }

                // Begin the move operation now that we are past pre-checks.
                var existingChild = this.Project.FindNodeByFullPath(moniker);
                if (isLink)
                {
                    // links we just want to update the link node for...
                    if (existingChild != null)
                    {
                        if (ComUtilities.IsSameComObject(this.Project, project))
                        {
                            if (this.DropEffect != DropEffect.Move)
                            {
                                Utilities.ShowMessageBox(
                                        this.Project.Site,
                                        string.Format("Cannot copy linked files within the same project. You cannot have more than one link to the same file in a project."),
                                        null,
                                        OLEMSGICON.OLEMSGICON_CRITICAL,
                                        OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                                return null;
                            }
                        }
                        else
                        {
                            Utilities.ShowMessageBox(
                                    this.Project.Site,
                                    string.Format("There is already a link to '{0}'. You cannot have more than one link to the same file in a project.", moniker),
                                    null,
                                    OLEMSGICON.OLEMSGICON_CRITICAL,
                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                            return null;
                        }
                    }

                    return new ReparentLinkedFileAddition(this.Project, targetFolder, moniker);
                }

                var newPath = Path.Combine(targetFolder, Path.GetFileName(moniker));
                if (File.Exists(newPath) &&
                    CommonUtils.IsSamePath(
                        NativeMethods.GetAbsolutePathToDirectory(newPath),
                        NativeMethods.GetAbsolutePathToDirectory(moniker)))
                {
                    newPath = GetCopyName(newPath);
                }

                var ok = false;
                if (this.DropEffect == DropEffect.Move && Utilities.IsSameComObject(project, this.Project))
                {
                    if (existingChild != null && existingChild.ItemNode != null && existingChild.ItemNode.IsExcluded)
                    {
                        // https://nodejstools.codeplex.com/workitem/271
                        // The item is excluded, so we don't need to ask if we can rename it.
                        ok = true;
                    }
                    else
                    {
                        ok = this.Project.Tracker.CanRenameItem(moniker, newPath, VSRENAMEFILEFLAGS.VSRENAMEFILEFLAGS_NoFlags);
                    }
                }
                else
                {
                    ok = this.Project.Tracker.CanAddItems(
                        new[] { newPath },
                        new VSQUERYADDFILEFLAGS[] { VSQUERYADDFILEFLAGS.VSQUERYADDFILEFLAGS_NoFlags });
                }

                if (ok)
                {
                    if (File.Exists(newPath))
                    {
                        if (this.DropEffect == DropEffect.Move &&
                            Utilities.IsSameComObject(project, this.Project) &&
                            this.Project.FindNodeByFullPath(newPath) != null)
                        {
                            // if we're overwriting an item, we're moving it, make sure that's ok.
                            // OverwriteFileAddition will handle the remove from the hierarchy
                            if (!this.Project.Tracker.CanRemoveItems(new[] { newPath }, new[] { VSQUERYREMOVEFILEFLAGS.VSQUERYREMOVEFILEFLAGS_NoFlags }))
                            {
                                return null;
                            }
                        }
                        var overwrite = this.OverwriteAllItems;

                        if (overwrite == null)
                        {
                            if (!PromptOverwriteFile(moniker, out var dialog))
                            {
                                return null;
                            }

                            overwrite = dialog.ShouldOverwrite;

                            if (dialog.AllItems)
                            {
                                this.OverwriteAllItems = overwrite;
                            }
                        }

                        if (overwrite.Value)
                        {
                            return new OverwriteFileAddition(this.Project, targetFolder, this.DropEffect, moniker, Path.GetFileName(newPath), project);
                        }
                        else
                        {
                            return SkipOverwriteAddition.Instance;
                        }
                    }
                    else if (Directory.Exists(newPath))
                    {
                        Utilities.ShowMessageBox(
                            this.Project.Site,
                            SR.GetString(SR.DirectoryExists, CommonUtils.GetFileOrDirectoryName(newPath)),
                            null,
                            OLEMSGICON.OLEMSGICON_CRITICAL,
                            OLEMSGBUTTON.OLEMSGBUTTON_OK,
                            OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                        return null;
                    }

                    if (newPath.Length >= NativeMethods.MAX_PATH)
                    {
                        Utilities.ShowMessageBox(
                            this.Project.Site,
                            SR.GetString(SR.PathTooLongShortMessage),
                            null,
                            OLEMSGICON.OLEMSGICON_CRITICAL,
                            OLEMSGBUTTON.OLEMSGBUTTON_OK,
                            OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                        return null;
                    }
                    return new FileAddition(this.Project, targetFolder, this.DropEffect, moniker, Path.GetFileName(newPath), project);
                }
                return null;
            }