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>(); }
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; }
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; }
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)); } }
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); }
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); }
public void GetStagedStatus(ObjectId firstRevision, ObjectId secondRevision, ObjectId parentToSecond, StagedStatus status) { var stagedStatus = _gitModule.GetTestAccessor().GetStagedStatus(firstRevision, secondRevision, parentToSecond); Assert.AreEqual(status, stagedStatus); }
public TreeFileData(string name, FileStatus fileStatus, ConflictType conflictType, StagedStatus stagedStatus) : base(name, fileStatus, stagedStatus) { _conflictType = conflictType; }
protected TreeItemData(string name, FileStatus fileStatus, StagedStatus stagedStatus) { _name = name; _fileStatus = fileStatus; _stagedStatus = stagedStatus; }
/// <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); }
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>(); }
/// <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); }
protected TreeItemData(string name, FileStatus fileStatus, StagedStatus stagedStatus) { Name = name; FileStatus = fileStatus; StagedStatus = stagedStatus; }
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; }