using System; using System.Collections.Generic; using System.Text; namespace SourceGit.Models { public class DiffOption { public bool IsLocalChange => _revisions.Count == 0; public bool IsUnstaged => _isUnstaged; public List Revisions => _revisions; public string Path => _path; public string OrgPath => _orgPath; /// /// Only used for working copy changes /// /// /// public DiffOption(Change change, bool isUnstaged) { _isUnstaged = isUnstaged; _path = change.Path; _orgPath = change.OriginalPath; if (isUnstaged) { switch (change.WorkTree) { case ChangeState.Added: case ChangeState.Untracked: _extra = "--no-index"; _orgPath = "/dev/null"; break; } } else { if (change.DataForAmend != null) _extra = $"--cached {change.DataForAmend.ParentSHA}"; else _extra = "--cached"; } } /// /// Only used for commit changes. /// /// /// public DiffOption(Commit commit, Change change) { _revisions.Add(commit.FirstParentToCompare); _revisions.Add(commit.SHA); _path = change.Path; _orgPath = change.OriginalPath; } /// /// Used to diff in `FileHistory` /// /// public DiffOption(FileVersion ver) { if (string.IsNullOrEmpty(ver.OriginalPath)) { _revisions.Add(ver.HasParent ? $"{ver.SHA}^" : EmptyTreeHash.Guess(ver.SHA)); _revisions.Add(ver.SHA); _path = ver.Path; } else { _revisions.Add($"{ver.SHA}^:{ver.OriginalPath.Quoted()}"); _revisions.Add($"{ver.SHA}:{ver.Path.Quoted()}"); _path = ver.Path; _orgPath = ver.Change.OriginalPath; _ignorePaths = true; } } /// /// Used to diff two revisions in `FileHistory` /// /// /// public DiffOption(FileVersion start, FileVersion end) { if (start.Change.Index == ChangeState.Deleted) { _revisions.Add(EmptyTreeHash.Guess(end.SHA)); _revisions.Add(end.SHA); _path = end.Path; } else if (end.Change.Index == ChangeState.Deleted) { _revisions.Add(start.SHA); _revisions.Add(EmptyTreeHash.Guess(start.SHA)); _path = start.Path; } else if (!end.Path.Equals(start.Path, StringComparison.Ordinal)) { _revisions.Add($"{start.SHA}:{start.Path.Quoted()}"); _revisions.Add($"{end.SHA}:{end.Path.Quoted()}"); _path = end.Path; _orgPath = start.Path; _ignorePaths = true; } else { _revisions.Add(start.SHA); _revisions.Add(end.SHA); _path = start.Path; } } /// /// Used to show differences between two revisions. /// /// /// /// public DiffOption(string baseRevision, string targetRevision, Change change) { _revisions.Add(string.IsNullOrEmpty(baseRevision) ? "-R" : baseRevision); _revisions.Add(targetRevision); _path = change.Path; _orgPath = change.OriginalPath; } /// /// Converts to diff command arguments. /// public override string ToString() { var builder = new StringBuilder(); if (!string.IsNullOrEmpty(_extra)) builder.Append($"{_extra} "); foreach (var r in _revisions) builder.Append($"{r} "); if (_ignorePaths) return builder.ToString(); builder.Append("-- "); if (!string.IsNullOrEmpty(_orgPath)) builder.Append($"{_orgPath.Quoted()} "); builder.Append(_path.Quoted()); return builder.ToString(); } private readonly bool _isUnstaged = false; private readonly string _path; private readonly string _orgPath = string.Empty; private readonly string _extra = string.Empty; private readonly List _revisions = []; private readonly bool _ignorePaths = false; } }