Exemplo n.º 1
0
        public void ParseFromDiffTreeLine_ModifyBlobLine()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Modify,
                SourceIsDirectory = false,
                TargetIsDirectory = false,
                TargetPath        = Path.Combine(RepoRoot, TestBlobPath1.Replace('/', Path.DirectorySeparatorChar)),
                SourceSha         = TestSha1,
                TargetSha         = Test2Sha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(ModifyBlobLineFromDiffTree, RepoRoot);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 2
0
        public void ParseFromDiffTreeLine_BlobLineWithTreePath()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Add,
                SourceIsDirectory = false,
                TargetIsDirectory = false,
                TargetPath        = Path.Combine(RepoRoot, TestBlobPath2.Replace('/', Path.DirectorySeparatorChar)),
                SourceSha         = null,
                TargetSha         = TestSha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromLsTreeLine(BlobLineWithTreePathFromLsTree, RepoRoot);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 3
0
        public void ParseFromDiffTreeLine_AddTreeLine()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Add,
                SourceIsDirectory = false,
                TargetIsDirectory = true,
                TargetPath        = CreateTreePath(TestTreePath1),
                SourceSha         = EmptySha1,
                TargetSha         = Test2Sha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(AddTreeLineFromDiffTree, RepoRoot);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 4
0
        public void ParseFromDiffTreeLine_TreeLineWithBlobPath()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Add,
                SourceIsDirectory = false,
                TargetIsDirectory = true,
                TargetPath        = CreateTreePath(TestTreePath2),
                SourceSha         = null,
                TargetSha         = null
            };

            DiffTreeResult result = DiffTreeResult.ParseFromLsTreeLine(TreeLineWithBlobPathFromLsTree, RepoRoot);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 5
0
        public void ParseFromDiffTreeLine_ModifyTreeLine()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Modify,
                SourceIsDirectory = true,
                TargetIsDirectory = true,
                TargetPath        = CreateTreePath(TestTreePath1),
                SourceSha         = TestSha1,
                TargetSha         = Test2Sha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(ModifyTreeLineFromDiffTree);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 6
0
        public void ParseFromDiffTreeLine_DeleteBlobLine2()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Delete,
                SourceIsDirectory = false,
                TargetIsDirectory = false,
                TargetPath        = TestBlobPath1.Replace('/', Path.DirectorySeparatorChar),
                SourceSha         = TestSha1,
                TargetSha         = EmptySha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(DeleteBlobLineFromDiffTree2);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 7
0
        public void ParseFromDiffTreeLine_EmptyRepo()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Modify,
                SourceIsDirectory = true,
                TargetIsDirectory = true,
                TargetPath        = TestTreePath1.Replace('/', Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar,
                SourceSha         = TestSha1,
                TargetSha         = Test2Sha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(ModifyTreeLineFromDiffTree, string.Empty);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 8
0
        public void ParseFromLsTreeLine_BlobLine()
        {
            DiffTreeResult expected = new DiffTreeResult()
            {
                Operation         = DiffTreeResult.Operations.Add,
                SourceIsDirectory = false,
                TargetIsDirectory = false,
                TargetPath        = TestTreePath1.Replace('/', Path.DirectorySeparatorChar),
                SourceSha         = null,
                TargetSha         = TestSha1
            };

            DiffTreeResult result = DiffTreeResult.ParseFromLsTreeLine(BlobLineFromLsTree);

            this.ValidateDiffTreeResult(expected, result);
        }
Exemplo n.º 9
0
        /// <remarks>
        /// This is not used in a multithreaded method, it doesn't need to be thread-safe
        /// </remarks>
        private void EnqueueFileAddOperation(ITracer activity, DiffTreeResult operation)
        {
            // Each filepath should be unique according to GVFSPlatform.Instance.Constants.PathComparer.
            // If there are duplicates, only the last parsed one should remain.
            if (!this.filesAdded.Add(operation.TargetPath))
            {
                foreach (KeyValuePair <string, HashSet <PathWithMode> > kvp in this.FileAddOperations)
                {
                    PathWithMode tempPathWithMode = new PathWithMode(operation.TargetPath, 0x0000);
                    if (kvp.Value.Remove(tempPathWithMode))
                    {
                        break;
                    }
                }
            }

            if (this.stagedFileDeletes.Remove(operation.TargetPath))
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add(nameof(operation.TargetPath), operation.TargetPath);
                metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);
            }

            this.FileAddOperations.AddOrUpdate(
                operation.TargetSha,
                new HashSet <PathWithMode> {
                new PathWithMode(operation.TargetPath, operation.TargetMode)
            },
                (key, oldValue) =>
            {
                oldValue.Add(new PathWithMode(operation.TargetPath, operation.TargetMode));
                return(oldValue);
            });

            this.RequiredBlobs.Add(operation.TargetSha);
        }
Exemplo n.º 10
0
        /// <remarks>
        /// This is not used in a multithreaded method, it doesn't need to be thread-safe
        /// </remarks>
        private void EnqueueFileAddOperation(ITracer activity, DiffTreeResult operation)
        {
            // Each filepath should be case-insensitive unique. If there are duplicates, only the last parsed one should remain.
            if (!this.filesAdded.Add(operation.TargetPath))
            {
                foreach (KeyValuePair <string, HashSet <string> > kvp in this.FileAddOperations)
                {
                    if (kvp.Value.Remove(operation.TargetPath))
                    {
                        break;
                    }
                }
            }

            if (this.stagedFileDeletes.Remove(operation.TargetPath))
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add(nameof(operation.TargetPath), operation.TargetPath);
                metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);
            }

            this.FileAddOperations.AddOrUpdate(
                operation.TargetSha,
                new HashSet <string>(StringComparer.OrdinalIgnoreCase)
            {
                operation.TargetPath
            },
                (key, oldValue) =>
            {
                oldValue.Add(operation.TargetPath);
                return(oldValue);
            });

            this.RequiredBlobs.Add(operation.TargetSha);
        }
Exemplo n.º 11
0
        protected bool TryDownloadRootGitAttributes(GVFSEnlistment enlistment, GVFSGitObjects gitObjects, GitRepo repo, out string error)
        {
            List <DiffTreeResult> rootEntries = new List <DiffTreeResult>();
            GitProcess            git         = new GitProcess(enlistment);

            GitProcess.Result result = git.LsTree(
                GVFSConstants.DotGit.HeadName,
                line => rootEntries.Add(DiffTreeResult.ParseFromLsTreeLine(line, repoRoot: string.Empty)),
                recursive: false);

            if (result.ExitCodeIsFailure)
            {
                error = "Error returned from ls-tree to find " + GVFSConstants.SpecialGitFiles.GitAttributes + " file: " + result.Errors;
                return(false);
            }

            DiffTreeResult gitAttributes = rootEntries.FirstOrDefault(entry => entry.TargetPath.Equals(GVFSConstants.SpecialGitFiles.GitAttributes));

            if (gitAttributes == null)
            {
                error = "This branch does not contain a " + GVFSConstants.SpecialGitFiles.GitAttributes + " file in the root folder.  This file is required by GVFS clone";
                return(false);
            }

            if (!repo.ObjectExists(gitAttributes.TargetSha))
            {
                if (gitObjects.TryDownloadAndSaveObject(gitAttributes.TargetSha, GVFSGitObjects.RequestSource.GVFSVerb) != GitObjects.DownloadAndSaveObjectResult.Success)
                {
                    error = "Could not download " + GVFSConstants.SpecialGitFiles.GitAttributes + " file";
                    return(false);
                }
            }

            error = null;
            return(true);
        }
Exemplo n.º 12
0
        private void EnqueueOperationsFromDiffTreeLine(ITracer activity, string line)
        {
            if (!line.StartsWith(":"))
            {
                // Diff-tree starts with metadata we can ignore.
                // Real diff lines always start with a colon
                return;
            }

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(line);

            if (!this.ShouldIncludeResult(result))
            {
                return;
            }

            if (result.Operation == DiffTreeResult.Operations.Unknown ||
                result.Operation == DiffTreeResult.Operations.Unmerged ||
                result.Operation == DiffTreeResult.Operations.CopyEdit ||
                result.Operation == DiffTreeResult.Operations.RenameEdit)
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add(nameof(result.TargetPath), result.TargetPath);
                metadata.Add(nameof(line), line);
                activity.RelatedError(metadata, "Unexpected diff operation: " + result.Operation);
                this.HasFailures = true;
                return;
            }

            // Separate and enqueue all directory operations first.
            if (result.SourceIsDirectory || result.TargetIsDirectory)
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add(nameof(result.TargetPath), result.TargetPath);
                        metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);
                    }

                    break;

                case DiffTreeResult.Operations.Add:
                case DiffTreeResult.Operations.Modify:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add(nameof(result.TargetPath), result.TargetPath);
                        metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);

                        // Replace the delete with the add to make sure we don't delete a folder from under ourselves
                        this.stagedDirectoryOperations.Remove(result);
                        this.stagedDirectoryOperations.Add(result);
                    }

                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
            else
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    this.EnqueueFileDeleteOperation(activity, result.TargetPath);

                    break;

                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.Add:
                    this.EnqueueFileAddOperation(activity, result);
                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
        }
Exemplo n.º 13
0
 public void ParseFromLsTreeLine_NullLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromLsTreeLine(null));
 }
Exemplo n.º 14
0
 public void ParseFromLsTreeLine_EmptyLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromLsTreeLine(string.Empty));
 }
Exemplo n.º 15
0
 public void ParseFromDiffTreeLine_TwoPathLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromDiffTreeLine(TwoPathLineFromDiffTree));
 }
Exemplo n.º 16
0
 public void TestGetIndexOfTypeMarker(string line, string typeMarker, bool expectedResult)
 {
     DiffTreeResult.IsLsTreeLineOfType(line, typeMarker).ShouldEqual(expectedResult);
 }
Exemplo n.º 17
0
 public void ParseFromDiffTreeLine_TooManyFieldsLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromDiffTreeLine(TooManyFieldsLineFromDiffTree));
 }
Exemplo n.º 18
0
 public void ParseFromDiffTreeLine_NotEnoughFieldsLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromDiffTreeLine(NotEnoughFieldsLineFromDiffTree));
 }
Exemplo n.º 19
0
 public void ParseFromDiffTreeLine_NoColonLine()
 {
     Assert.Throws <ArgumentException>(() => DiffTreeResult.ParseFromDiffTreeLine(MissingColonLineFromDiffTree));
 }
Exemplo n.º 20
0
 public void ParseFromLsTreeLine_InvalidLine()
 {
     DiffTreeResult.ParseFromLsTreeLine(InvalidLineFromLsTree).ShouldBeNull();
 }
Exemplo n.º 21
0
        private void EnqueueOperationsFromDiffTreeLine(ITracer activity, string repoRoot, string line)
        {
            if (!line.StartsWith(":"))
            {
                // Diff-tree starts with metadata we can ignore.
                // Real diff lines always start with a colon
                return;
            }

            DiffTreeResult result = DiffTreeResult.ParseFromDiffTreeLine(line, repoRoot);

            if (!this.ShouldIncludeResult(result))
            {
                return;
            }

            if (result.Operation == DiffTreeResult.Operations.Unknown ||
                result.Operation == DiffTreeResult.Operations.Unmerged)
            {
                EventMetadata metadata = new EventMetadata();
                metadata.Add("Path", result.TargetFilename);
                activity.RelatedError(metadata, "Unexpected diff operation: " + result.Operation);
                this.HasFailures = true;
                return;
            }

            // Separate and enqueue all directory operations first.
            if (result.SourceIsDirectory || result.TargetIsDirectory)
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);
                    }

                    break;

                case DiffTreeResult.Operations.RenameEdit:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        // This could happen if a directory was deleted and an existing directory was renamed to replace it, but with a different case.
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);

                        // The target of RenameEdit is always akin to an Add, so replacing the delete is the safer thing to do.
                        this.stagedDirectoryOperations.Remove(result);
                        this.stagedDirectoryOperations.Add(result);
                    }

                    if (!result.TargetIsDirectory)
                    {
                        // Handle when a directory becomes a file.
                        // Files becoming directories is handled by HandleAllDirectoryOperations
                        this.EnqueueFileAddOperation(activity, result);
                    }

                    if (!result.SourceIsDirectory)
                    {
                        // Handle when a file becomes a directory by deleting the file.
                        this.EnqueueFileDeleteOperation(activity, result.SourceFilename);
                    }

                    break;

                case DiffTreeResult.Operations.Add:
                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.CopyEdit:
                    if (!this.stagedDirectoryOperations.Add(result))
                    {
                        EventMetadata metadata = new EventMetadata();
                        metadata.Add("Filename", result.TargetFilename);
                        metadata.Add(TracingConstants.MessageKey.WarningMessage, "A case change was attempted. It will not be reflected in the working directory.");
                        activity.RelatedEvent(EventLevel.Warning, "CaseConflict", metadata);

                        // Replace the delete with the add to make sure we don't delete a folder from under ourselves
                        this.stagedDirectoryOperations.Remove(result);
                        this.stagedDirectoryOperations.Add(result);
                    }

                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
            else
            {
                switch (result.Operation)
                {
                case DiffTreeResult.Operations.Delete:
                    this.EnqueueFileDeleteOperation(activity, result.TargetFilename);

                    break;

                case DiffTreeResult.Operations.RenameEdit:

                    this.EnqueueFileAddOperation(activity, result);
                    this.EnqueueFileDeleteOperation(activity, result.SourceFilename);

                    break;

                case DiffTreeResult.Operations.Modify:
                case DiffTreeResult.Operations.CopyEdit:
                case DiffTreeResult.Operations.Add:
                    this.EnqueueFileAddOperation(activity, result);
                    break;

                default:
                    activity.RelatedError("Unexpected diff operation from line: {0}", line);
                    break;
                }
            }
        }
Exemplo n.º 22
0
 public void ParseFromLsTreeLine_NullRepoRoot()
 {
     Assert.Throws <ArgumentNullException>(() => DiffTreeResult.ParseFromLsTreeLine(BlobLineFromLsTree, null));
 }
Exemplo n.º 23
0
 public void ParseFromDiffTreeLine_NullRepo()
 {
     Assert.Throws <ArgumentNullException>(() => DiffTreeResult.ParseFromDiffTreeLine(ModifyTreeLineFromDiffTree, null));
 }