示例#1
0
        public static DiffTreeResult ParseFromDiffTreeLine(string line, string repoRoot)
        {
            line = line.Substring(1);

            // Filenames may contain spaces, but always follow a \t. Other fields are space delimited.
            string[] parts = line.Split('\t');
            parts = parts[0].Split(' ').Concat(parts.Skip(1)).ToArray();

            DiffTreeResult result = new DiffTreeResult();

            result.SourceIsDirectory = ValidTreeModes.Contains(parts[0]);
            result.TargetIsDirectory = ValidTreeModes.Contains(parts[1]);
            result.SourceSha         = parts[2];
            result.TargetSha         = parts[3];
            result.Operation         = DiffTreeResult.ParseOperation(parts[4]);
            result.TargetFilename    = ConvertPathToAbsoluteUtf8Path(repoRoot, parts.Last());
            result.SourceFilename    = parts.Length == 7 ? ConvertPathToAbsoluteUtf8Path(repoRoot, parts[5]) : null;
            return(result);
        }
        public static DiffTreeResult ParseFromDiffTreeLine(string line)
        {
            if (string.IsNullOrEmpty(line))
            {
                throw new ArgumentException("Line to parse cannot be null or empty", nameof(line));
            }

            /*
             * The lines passed to this method should be the result of a call to git diff-tree -r -t (sourceTreeish) (targetTreeish)
             *
             * Example output lines from git diff-tree
             * :000000 040000 0000000000000000000000000000000000000000 cee82f9d431bf610404f67bcdda3fee76f0c1dd5 A\tGVFS/FastFetch/Git
             * :000000 100644 0000000000000000000000000000000000000000 cdc036f9d561f14d908e0a0c337105b53c778e5e A\tGVFS/FastFetch/Git/FastFetchGitObjects.cs
             * :040000 000000 f68b90da732791438d67c0326997a2d26e4c2de4 0000000000000000000000000000000000000000 D\tGVFS/GVFS.CLI
             * :100644 000000 1242fc97c612ff286a5f1221d569508600ca5e06 0000000000000000000000000000000000000000 D\tGVFS/GVFS.CLI/GVFS.CLI.csproj
             * :040000 040000 3823348f91113a619eed8f48fe597cc9c7d088d8 fd56ff77b12a0b76567cb55ed4950272eac8b8f6 M\tGVFS/GVFS.Common
             * :100644 100644 57d9c737c8a48632cfbb12cae00c97d512b9f155 524d7dbcebd33e4007c52711d3f21b17373de454 M\tGVFS/GVFS.Common/GVFS.Common.csproj
             *  ^-[0]  ^-[1]  ^-[2]                                    ^-[3]                                    ^-[4]
             *                                                                                                   ^-tab
             *                                                                                                     ^-[5]
             *
             * This output will only happen if -C or -M is passed to the diff-tree command
             * Since we are not passing those options we shouldn't have to handle this format.
             * :100644 100644 3ac7d60a25bb772af1d5843c76e8a070c062dc5d c31a95125b8a6efd401488839a7ed1288ce01634 R094\tGVFS/GVFS.CLI/CommandLine/CloneVerb.cs\tGVFS/GVFS/CommandLine/CloneVerb.cs
             */

            if (!line.StartsWith(":"))
            {
                throw new ArgumentException($"diff-tree lines should start with a :", nameof(line));
            }

            // Skip the colon at the front
            line = line.Substring(1);

            // Filenames may contain spaces, but always follow a \t. Other fields are space delimited.
            // Splitting on \t will give us the mode, sha, operation in parts[0] and that path in parts[1] and optionally in paths[2]
            string[] parts = line.Split(new[] { '\t' }, count: 2);

            // Take the mode, sha, operation part and split on a space then add the paths that were split on a tab to the end
            parts = parts[0].Split(' ').Concat(parts.Skip(1)).ToArray();

            if (parts.Length != 6 ||
                parts[5].Contains('\t'))
            {
                // Look at file history to see how -C -M with 7 parts could be handled
                throw new ArgumentException($"diff-tree lines should have 6 parts unless passed -C or -M which this method doesn't handle", nameof(line));
            }

            DiffTreeResult result = new DiffTreeResult();

            result.SourceIsDirectory = ValidTreeModes.Contains(parts[0]);
            result.TargetIsDirectory = ValidTreeModes.Contains(parts[1]);
            result.SourceMode        = Convert.ToUInt16(parts[0], 8);
            result.TargetMode        = Convert.ToUInt16(parts[1], 8);

            if (!result.TargetIsDirectory)
            {
                result.TargetIsSymLink = result.TargetMode == SymLinkFileIndexEntry;
            }

            result.SourceSha  = parts[2];
            result.TargetSha  = parts[3];
            result.Operation  = DiffTreeResult.ParseOperation(parts[4]);
            result.TargetPath = ConvertPathToUtf8Path(parts[5]);
            if (result.TargetIsDirectory || result.SourceIsDirectory)
            {
                // Since diff-tree is not doing rename detection, file->directory or directory->file transformations are always multiple lines
                // with a delete line and an add line
                // :000000 040000 0000000000000000000000000000000000000000 cee82f9d431bf610404f67bcdda3fee76f0c1dd5 A\tGVFS/FastFetch/Git
                // :040000 040000 3823348f91113a619eed8f48fe597cc9c7d088d8 fd56ff77b12a0b76567cb55ed4950272eac8b8f6 M\tGVFS/GVFS.Common
                // :040000 000000 f68b90da732791438d67c0326997a2d26e4c2de4 0000000000000000000000000000000000000000 D\tGVFS/GVFS.CLI
                result.TargetPath = AppendPathSeparatorIfNeeded(result.TargetPath);
            }

            return(result);
        }