Esempio n. 1
0
 public TreeDirectoryData(string name, string shortName, TreeDirectoryData parent, FileStatus fileStatus, StagedStatus stagedStatus)
     : base(name, fileStatus, stagedStatus)
 {
     _parent = parent;
     ShortName = shortName;
     _files = new List<TreeFileData>();
     _directories = new List<TreeDirectoryData>();
 }
Esempio n. 2
0
 protected TreeItem(Repository repository, string relativePath,
                    TreeDirectory parent, FileStatus status, string name)
     : base(repository, name)
 {
     _parent = parent;
     if (parent != null)
     {
         _stagedStatus = parent._stagedStatus;
     }
     _status       = status;
     _relativePath = relativePath;
 }
Esempio n. 3
0
 protected TreeItem(Repository repository, string relativePath,
     TreeDirectory parent, FileStatus status, string name)
     : base(repository, name)
 {
     _parent = parent;
     if(parent != null)
     {
         _stagedStatus = parent._stagedStatus;
     }
     _status = status;
     _relativePath = relativePath;
 }
Esempio n. 4
0
        public void GetDiffChangedFilesFromString(string testName, StagedStatus stagedStatus, string statusString)
        {
            // TODO produce a valid working directory
            GitModule module = new(Path.GetTempPath());

            using (ApprovalResults.ForScenario(testName.Replace(' ', '_')))
            {
                // git diff --find-renames --find-copies -z --name-status
                var statuses = module.GetTestAccessor().GetDiffChangedFilesFromString(statusString, stagedStatus);
                Approvals.VerifyJson(JsonConvert.SerializeObject(statuses));
            }
        }
        public void TestGetDiffChangedFilesFromString(string testName, StagedStatus stagedStatus, string statusString)
        {
            // TODO produce a valid working directory
            var module = new GitModule(Path.GetTempPath());

            using (ApprovalResults.ForScenario(testName.Replace(' ', '_')))
            {
                // git diff -M -C -z --name-status
                var statuses = GitCommandHelpers.GetDiffChangedFilesFromString(module, statusString, stagedStatus);
                Approvals.VerifyJson(JsonConvert.SerializeObject(statuses));
            }
        }
Esempio n. 6
0
        public static GitItemStatus FromStatusCharacter(StagedStatus staged, string fileName, char x)
        {
            var isNew = x == 'A' || x == '?' || x == '!';

            return(new GitItemStatus(fileName)
            {
                IsNew = isNew,
                IsChanged = x == 'M',
                IsDeleted = x == 'D',
                IsSkipWorktree = x == 'S',
                IsRenamed = x == 'R',
                IsCopied = x == 'C',
                IsTracked = (x != '?' && x != '!' && x != ' ') || !isNew,
                IsIgnored = x == '!',
                IsConflict = x == 'U',
                Staged = staged
            });
        }
        /// <summary>
        /// Parse the output from git-diff --name-status
        /// </summary>
        /// <param name="module">The Git module</param>
        /// <param name="statusString">output from the git command</param>
        /// <param name="firstRevision">from revision string</param>
        /// <param name="secondRevision">to revision</param>
        /// <param name="parentToSecond">The parent for the second revision</param>
        /// <returns>list with the parsed GitItemStatus</returns>
        /// <seealso href="https://git-scm.com/docs/git-diff"/>
        /// <remarks>Git revisions are required to determine if the <see cref="GitItemStatus"/> are WorkTree or Index.</remarks>
        public static IReadOnlyList <GitItemStatus> GetDiffChangedFilesFromString(IGitModule module, string statusString, [CanBeNull] string firstRevision, [CanBeNull] string secondRevision, [CanBeNull] string parentToSecond)
        {
            StagedStatus staged = StagedStatus.Unknown;

            if (firstRevision == GitRevision.IndexGuid && secondRevision == GitRevision.UnstagedGuid)
            {
                staged = StagedStatus.WorkTree;
            }
            else if (firstRevision == parentToSecond && secondRevision == GitRevision.IndexGuid)
            {
                staged = StagedStatus.Index;
            }
            else if ((firstRevision.IsNotNullOrWhitespace() && !firstRevision.IsArtificial()) ||
                     (secondRevision.IsNotNullOrWhitespace() && !secondRevision.IsArtificial()) ||
                     parentToSecond.IsNotNullOrWhitespace())
            {
                // This cannot be a worktree/index file
                staged = StagedStatus.None;
            }

            return(GetAllChangedFilesFromString_v1(module, statusString, true, staged));
        }
        private static GitItemStatus GitItemStatusFromCopyRename(StagedStatus staged, bool fromDiff, string nextFile, string fileName, char x, string status)
        {
            var gitItemStatus = new GitItemStatus();

            // Find renamed files...
            if (fromDiff)
            {
                gitItemStatus.OldName = fileName;
                gitItemStatus.Name    = nextFile;
            }
            else
            {
                gitItemStatus.Name    = fileName;
                gitItemStatus.OldName = nextFile;
            }

            gitItemStatus.IsNew     = false;
            gitItemStatus.IsChanged = false;
            gitItemStatus.IsDeleted = false;
            if (x == 'R')
            {
                gitItemStatus.IsRenamed = true;
            }
            else
            {
                gitItemStatus.IsCopied = true;
            }

            gitItemStatus.IsTracked = true;
            if (status.Length > 2)
            {
                gitItemStatus.RenameCopyPercentage = status.Substring(1);
            }

            gitItemStatus.Staged = staged;

            return(gitItemStatus);
        }
 /// <summary>
 /// Parse the output from git-diff --name-status
 /// </summary>
 /// <param name="module">The Git module</param>
 /// <param name="statusString">output from the git command</param>
 /// <param name="staged">required to determine if <see cref="StagedStatus"/> allows stage/unstage.</param>
 /// <returns>list with the parsed GitItemStatus</returns>
 /// <seealso href="https://git-scm.com/docs/git-diff"/>
 public static IReadOnlyList <GitItemStatus> GetDiffChangedFilesFromString(IGitModule module, string statusString, StagedStatus staged)
 {
     return(GetAllChangedFilesFromString_v1(module, statusString, true, staged));
 }
        public void TestGetStagedStatus(ObjectId firstRevision, ObjectId secondRevision, ObjectId parentToSecond, StagedStatus status)
        {
            var stagedStatus = GitCommandHelpers.GetStagedStatus(firstRevision, secondRevision, parentToSecond);

            Assert.AreEqual(status, stagedStatus);
        }
Esempio n. 11
0
        private static TreeDirectoryData BreakIntoTree(IDictionary <string, TreeFileData> files, StagedStatus stagedStatus)
        {
            var root = new TreeDirectoryData("", "", null, FileStatus.Cached, stagedStatus);
            var dirs = new Dictionary <string, TreeDirectoryData>();
            var path = new StringBuilder();

            foreach (var tfinfo in files.Values)
            {
                var parent     = root;
                var name       = tfinfo.Name;
                var nameLength = name.Length;
                //if(name.EndsWith("/"))
                //{
                //    --nameLength;
                //    name = name.Substring(0, nameLength);
                //}
                int slashPos = 0;
                path.Clear();
                while (slashPos != -1 && slashPos < nameLength)
                {
                    bool isFile;
                    int  endOfPathName = name.IndexOf('/', slashPos);
                    if (endOfPathName == -1)
                    {
                        endOfPathName = nameLength;
                        isFile        = true;
                    }
                    else
                    {
                        isFile = false;
                    }
                    string partName;
                    if (isFile)
                    {
                        partName = slashPos == 0 ?
                                   name :
                                   name.Substring(slashPos, endOfPathName - slashPos);
                        tfinfo.ShortName = partName;
                        parent.AddFile(tfinfo);
                        break;
                    }
                    else
                    {
                        partName = name.Substring(slashPos, endOfPathName - slashPos);
                        path.Append(partName);
                        path.Append('/');
                        string            currentPath = path.ToString();
                        TreeDirectoryData wtDirectory;
                        if (!dirs.TryGetValue(currentPath, out wtDirectory))
                        {
                            wtDirectory = new TreeDirectoryData(currentPath, partName, parent, FileStatus.Cached, stagedStatus);
                            dirs.Add(currentPath, wtDirectory);
                            parent.AddDirectory(wtDirectory);
                        }
                        parent = wtDirectory;
                    }
                    slashPos = endOfPathName + 1;
                }
            }

            return(root);
        }
Esempio n. 12
0
        public void GetStagedStatus(ObjectId firstRevision, ObjectId secondRevision, ObjectId parentToSecond, StagedStatus status)
        {
            var stagedStatus = _gitModule.GetTestAccessor().GetStagedStatus(firstRevision, secondRevision, parentToSecond);

            Assert.AreEqual(status, stagedStatus);
        }
Esempio n. 13
0
 public TreeFileData(string name, FileStatus fileStatus, ConflictType conflictType, StagedStatus stagedStatus)
     : base(name, fileStatus, stagedStatus)
 {
     _conflictType = conflictType;
 }
Esempio n. 14
0
 protected TreeItemData(string name, FileStatus fileStatus, StagedStatus stagedStatus)
 {
     _name = name;
     _fileStatus = fileStatus;
     _stagedStatus = stagedStatus;
 }
Esempio n. 15
0
        /// <summary>
        /// Parse git-status --porcelain=1 and git-diff --name-status
        /// Outputs are similar, except that git-status has status for both worktree and index
        /// </summary>
        private static IReadOnlyList <GitItemStatus> GetAllChangedFilesFromString_v1(IGitModule module, string statusString, bool fromDiff, StagedStatus staged)
        {
            var diffFiles = new List <GitItemStatus>();

            if (string.IsNullOrEmpty(statusString))
            {
                return(diffFiles);
            }

            // The status string from git-diff can show warnings. See tests
            var    nl             = new[] { '\n', '\r' };
            string trimmedStatus  = statusString.Trim(nl);
            int    lastNewLinePos = trimmedStatus.LastIndexOfAny(nl);

            if (lastNewLinePos > 0)
            {
                int ind = trimmedStatus.LastIndexOf('\0');
                if (ind < lastNewLinePos)
                {
                    // Warning at end
                    lastNewLinePos = trimmedStatus.IndexOfAny(nl, ind >= 0 ? ind : 0);
                    trimmedStatus  = trimmedStatus.Substring(0, lastNewLinePos).Trim(nl);
                }
                else
                {
                    // Warning at beginning
                    trimmedStatus = trimmedStatus.Substring(lastNewLinePos).Trim(nl);
                }
            }

            // Doesn't work with removed submodules
            var submodules = module.GetSubmodulesLocalPaths();

            // Split all files on '\0' (WE NEED ALL COMMANDS TO BE RUN WITH -z! THIS IS ALSO IMPORTANT FOR ENCODING ISSUES!)
            var files = trimmedStatus.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

            for (int n = 0; n < files.Length; n++)
            {
                if (string.IsNullOrEmpty(files[n]))
                {
                    continue;
                }

                int splitIndex = files[n].IndexOfAny(new[] { '\0', '\t', ' ' }, 1);

                string status;
                string fileName;

                if (splitIndex < 0)
                {
                    status   = files[n];
                    fileName = files[n + 1];
                    n++;
                }
                else
                {
                    status   = files[n].Substring(0, splitIndex);
                    fileName = files[n].Substring(splitIndex);
                }

                char x = status[0];
                char y = status.Length > 1 ? status[1] : ' ';

                if (fromDiff && staged == StagedStatus.WorkTree && x == 'U')
                {
                    // git-diff has two lines to inform that a file is modified and has a merge conflict
                    continue;
                }

                if (x != '?' && x != '!' && x != ' ')
                {
                    GitItemStatus gitItemStatusX;
                    var           stagedX = fromDiff ? staged : StagedStatus.Index;
                    if (x == 'R' || x == 'C')
                    {
                        // Find renamed files...
                        string nextFile = n + 1 < files.Length ? files[n + 1] : "";
                        gitItemStatusX = GitItemStatusFromCopyRename(stagedX, fromDiff, nextFile, fileName, x, status);
                        n++;
                    }
                    else
                    {
                        gitItemStatusX = GitItemStatusFromStatusCharacter(stagedX, fileName, x);
                    }

                    if (submodules.Contains(gitItemStatusX.Name))
                    {
                        gitItemStatusX.IsSubmodule = true;
                    }

                    diffFiles.Add(gitItemStatusX);
                }

                if (fromDiff || y == ' ')
                {
                    continue;
                }

                GitItemStatus gitItemStatusY;
                var           stagedY = StagedStatus.WorkTree;
                if (y == 'R' || y == 'C')
                {
                    // Find renamed files...
                    string nextFile = n + 1 < files.Length ? files[n + 1] : "";
                    gitItemStatusY = GitItemStatusFromCopyRename(stagedY, false, nextFile, fileName, y, status);
                    n++;
                }
                else
                {
                    gitItemStatusY = GitItemStatusFromStatusCharacter(stagedY, fileName, y);
                }

                if (submodules.Contains(gitItemStatusY.Name))
                {
                    gitItemStatusY.IsSubmodule = true;
                }

                diffFiles.Add(gitItemStatusY);
            }

            return(diffFiles);
        }
Esempio n. 16
0
 public TreeDirectoryData(string name, string shortName, TreeDirectoryData parent, FileStatus fileStatus, StagedStatus stagedStatus)
     : base(name, fileStatus, stagedStatus)
 {
     Parent      = parent;
     ShortName   = shortName;
     Files       = new List <TreeFileData>();
     Directories = new List <TreeDirectoryData>();
 }
Esempio n. 17
0
 public TreeFileData(string name, FileStatus fileStatus, ConflictType conflictType, StagedStatus stagedStatus)
     : base(name, fileStatus, stagedStatus)
 {
     _conflictType = conflictType;
 }
Esempio n. 18
0
        /// <summary>
        /// Parse git-status --porcelain=1 and git-diff --name-status
        /// Outputs are similar, except that git-status has status for both worktree and index
        /// </summary>
        /// <param name="module">The GitModule</param>
        /// <param name="statusString">Output from Git command</param>
        /// <param name="fromDiff">Parse git-diff</param>
        /// <param name="staged">The staged status <see cref="GitItemStatus"/>, only relevant for git-diff (parsed for git-status)</param>
        /// <returns>list with the git items</returns>
        private static IReadOnlyList <GitItemStatus> GetAllChangedFilesFromString_v1(IGitModule module, string statusString, bool fromDiff, StagedStatus staged)
        {
            var diffFiles = new List <GitItemStatus>();

            if (string.IsNullOrEmpty(statusString))
            {
                return(diffFiles);
            }

            string trimmedStatus = RemoveWarnings(statusString);

            // Doesn't work with removed submodules
            var submodules = module.GetSubmodulesLocalPaths();

            // Split all files on '\0' (WE NEED ALL COMMANDS TO BE RUN WITH -z! THIS IS ALSO IMPORTANT FOR ENCODING ISSUES!)
            var files = trimmedStatus.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);

            for (int n = 0; n < files.Length; n++)
            {
                if (string.IsNullOrEmpty(files[n]))
                {
                    continue;
                }

                int splitIndex;
                if (fromDiff)
                {
                    splitIndex = -1;
                }
                else
                {
                    // Note that this fails for files with spaces (git-status --porcelain=1 is deprecated)
                    var splitChars = new[] { '\t', ' ' };
                    splitIndex = files[n].IndexOfAny(splitChars, 1);
                }

                string status;
                string fileName;

                if (splitIndex < 0)
                {
                    if (n >= files.Length - 1)
                    {
                        // Illegal, ignore
                        continue;
                    }

                    status   = files[n];
                    fileName = files[n + 1];
                    n++;
                }
                else
                {
                    status   = files[n].Substring(0, splitIndex);
                    fileName = files[n].Substring(splitIndex);
                }

                char x = status[0];
                char y = status.Length > 1 ? status[1] : ' ';

                if (fromDiff && staged == StagedStatus.WorkTree && x == 'U')
                {
                    // git-diff has two lines to inform that a file is modified and has a merge conflict
                    continue;
                }

                if (x != '?' && x != '!' && x != ' ')
                {
                    GitItemStatus gitItemStatusX;
                    var           stagedX = fromDiff ? staged : StagedStatus.Index;
                    if (x == 'R' || x == 'C')
                    {
                        // Find renamed files...
                        string nextFile = n + 1 < files.Length ? files[n + 1] : "";
                        gitItemStatusX = GitItemStatusFromCopyRename(stagedX, fromDiff, nextFile, fileName, x, status);
                        n++;
                    }
                    else
                    {
                        gitItemStatusX = GitItemStatusFromStatusCharacter(stagedX, fileName, x);
                    }

                    if (submodules.Contains(gitItemStatusX.Name))
                    {
                        gitItemStatusX.IsSubmodule = true;
                    }

                    diffFiles.Add(gitItemStatusX);
                }

                if (fromDiff || y == ' ')
                {
                    continue;
                }

                GitItemStatus gitItemStatusY;
                var           stagedY = StagedStatus.WorkTree;
                if (y == 'R' || y == 'C')
                {
                    // Find renamed files...
                    string nextFile = n + 1 < files.Length ? files[n + 1] : "";
                    gitItemStatusY = GitItemStatusFromCopyRename(stagedY, false, nextFile, fileName, y, status);
                    n++;
                }
                else
                {
                    gitItemStatusY = GitItemStatusFromStatusCharacter(stagedY, fileName, y);
                }

                if (submodules.Contains(gitItemStatusY.Name))
                {
                    gitItemStatusY.IsSubmodule = true;
                }

                diffFiles.Add(gitItemStatusY);
            }

            return(diffFiles);
        }
Esempio n. 19
0
 protected TreeItemData(string name, FileStatus fileStatus, StagedStatus stagedStatus)
 {
     Name         = name;
     FileStatus   = fileStatus;
     StagedStatus = stagedStatus;
 }
Esempio n. 20
0
        private static TreeDirectoryData BreakIntoTree(IDictionary<string, TreeFileData> files, StagedStatus stagedStatus)
        {
            var root = new TreeDirectoryData("", "", null, FileStatus.Cached, stagedStatus);
            var dirs = new Dictionary<string, TreeDirectoryData>();
            var path = new StringBuilder();

            foreach(var tfinfo in files.Values)
            {
                var parent = root;
                var name = tfinfo.Name;
                var nameLength = name.Length;
                //if(name.EndsWith("/"))
                //{
                //    --nameLength;
                //    name = name.Substring(0, nameLength);
                //}
                int slashPos = 0;
                path.Clear();
                while(slashPos != -1 && slashPos < nameLength)
                {
                    bool isFile;
                    int endOfPathName = name.IndexOf('/', slashPos);
                    if(endOfPathName == -1)
                    {
                        endOfPathName = nameLength;
                        isFile = true;
                    }
                    else
                    {
                        isFile = false;
                    }
                    string partName;
                    if(isFile)
                    {
                        partName = slashPos == 0 ?
                            name :
                            name.Substring(slashPos, endOfPathName - slashPos);
                        tfinfo.ShortName = partName;
                        parent.AddFile(tfinfo);
                        break;
                    }
                    else
                    {
                        partName = name.Substring(slashPos, endOfPathName - slashPos);
                        path.Append(partName);
                        path.Append('/');
                        string currentPath = path.ToString();
                        TreeDirectoryData wtDirectory;
                        if(!dirs.TryGetValue(currentPath, out wtDirectory))
                        {
                            wtDirectory = new TreeDirectoryData(currentPath, partName, parent, FileStatus.Cached, stagedStatus);
                            dirs.Add(currentPath, wtDirectory);
                            parent.AddDirectory(wtDirectory);
                        }
                        parent = wtDirectory;
                    }
                    slashPos = endOfPathName + 1;
                }
            }

            return root;
        }