using System.Text.RegularExpressions; namespace SourceGit.Git { /// /// Changed file status. /// public class Change { private static readonly Regex FORMAT = new Regex(@"^(\s?[\w\?]{1,4})\s+(.+)$"); /// /// Status Code /// public enum Status { None, Modified, Added, Deleted, Renamed, Copied, Unmerged, Untracked, } /// /// Index status /// public Status Index { get; set; } /// /// Work tree status. /// public Status WorkTree { get; set; } /// /// Current file path. /// public string Path { get; set; } /// /// Original file path before this revision. /// public string OriginalPath { get; set; } /// /// Staged(added) in index? /// public bool IsAddedToIndex { get { if (Index == Status.None || Index == Status.Untracked) return false; return true; } } /// /// Is conflict? /// public bool IsConflit { get { if (Index == Status.Unmerged || WorkTree == Status.Unmerged) return true; if (Index == Status.Added && WorkTree == Status.Added) return true; if (Index == Status.Deleted && WorkTree == Status.Deleted) return true; return false; } } /// /// Parse change for `--name-status` data. /// /// Raw data. /// Read from commit? /// Parsed change instance. public static Change Parse(string data, bool fromCommit = false) { var match = FORMAT.Match(data); if (!match.Success) return null; var change = new Change() { Path = match.Groups[2].Value }; var status = match.Groups[1].Value; if (fromCommit) { switch (status[0]) { case 'M': change.Set(Status.Modified); break; case 'A': change.Set(Status.Added); break; case 'D': change.Set(Status.Deleted); break; case 'R': change.Set(Status.Renamed); break; case 'C': change.Set(Status.Copied); break; default: return null; } } else { switch (status) { case " M": change.Set(Status.None, Status.Modified); break; case " A": change.Set(Status.None, Status.Added); break; case " D": change.Set(Status.None, Status.Deleted); break; case " R": change.Set(Status.None, Status.Renamed); break; case " C": change.Set(Status.None, Status.Copied); break; case "M": change.Set(Status.Modified, Status.None); break; case "MM": change.Set(Status.Modified, Status.Modified); break; case "MD": change.Set(Status.Modified, Status.Deleted); break; case "A": change.Set(Status.Added, Status.None); break; case "AM": change.Set(Status.Added, Status.Modified); break; case "AD": change.Set(Status.Added, Status.Deleted); break; case "D": change.Set(Status.Deleted, Status.None); break; case "R": change.Set(Status.Renamed, Status.None); break; case "RM": change.Set(Status.Renamed, Status.Modified); break; case "RD": change.Set(Status.Renamed, Status.Deleted); break; case "C": change.Set(Status.Copied, Status.None); break; case "CM": change.Set(Status.Copied, Status.Modified); break; case "CD": change.Set(Status.Copied, Status.Deleted); break; case "DR": change.Set(Status.Deleted, Status.Renamed); break; case "DC": change.Set(Status.Deleted, Status.Copied); break; case "DD": change.Set(Status.Deleted, Status.Deleted); break; case "AU": change.Set(Status.Added, Status.Unmerged); break; case "UD": change.Set(Status.Unmerged, Status.Deleted); break; case "UA": change.Set(Status.Unmerged, Status.Added); break; case "DU": change.Set(Status.Deleted, Status.Unmerged); break; case "AA": change.Set(Status.Added, Status.Added); break; case "UU": change.Set(Status.Unmerged, Status.Unmerged); break; case "??": change.Set(Status.Untracked, Status.Untracked); break; default: return null; } } if (change.Path[0] == '"') change.Path = change.Path.Substring(1, change.Path.Length - 2); if (!string.IsNullOrEmpty(change.OriginalPath) && change.OriginalPath[0] == '"') change.OriginalPath = change.OriginalPath.Substring(1, change.OriginalPath.Length - 2); return change; } private void Set(Status index, Status workTree = Status.None) { Index = index; WorkTree = workTree; if (index == Status.Renamed || workTree == Status.Renamed) { var idx = Path.IndexOf('\t'); if (idx >= 0) { OriginalPath = Path.Substring(0, idx); Path = Path.Substring(idx + 1); } else { idx = Path.IndexOf(" -> "); if (idx > 0) { OriginalPath = Path.Substring(0, idx); Path = Path.Substring(idx + 4); } } } } } }