public static LostObject TryParse(VsrModule module, string raw) { if (string.IsNullOrEmpty(raw)) { throw new ArgumentException("Raw source must be non-empty string", raw); } var patternMatch = RawDataRegex.Match(raw); // show failed assertion for unsupported cases (for developers) // if you get this message, // you can implement this format parsing // or post an issue to https://github.com/gitextensions/gitextensions/issues Debug.Assert(patternMatch.Success, "Lost object's extracted diagnostics format not implemented", raw); // skip unsupported raw data format (for end users) if (!patternMatch.Success) { return(null); } var matchedGroups = patternMatch.Groups; var rawType = matchedGroups[1].Value; var objectType = GetObjectType(matchedGroups[3]); var objectId = ObjectId.Parse(raw, matchedGroups[4]); var result = new LostObject(objectType, rawType, objectId); if (objectType == LostObjectType.Commit) { var commitLog = GetLostCommitLog(); var logPatternMatch = LogRegex.Match(commitLog); if (logPatternMatch.Success) { result.Author = module.ReEncodeStringFromLossless(logPatternMatch.Groups[1].Value); string encodingName = logPatternMatch.Groups[2].Value; result.Subject = module.ReEncodeCommitMessage(logPatternMatch.Groups[3].Value, encodingName); result.Date = DateTimeUtils.ParseUnixTime(logPatternMatch.Groups[4].Value); if (logPatternMatch.Groups.Count >= 5) { var parentId = logPatternMatch.Groups[5].Value.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault(); if (parentId != null) { result.Parent = ObjectId.Parse(parentId); } } } } else if (objectType == LostObjectType.Tag) { var tagData = GetLostTagData(); var tagPatternMatch = TagRegex.Match(tagData); if (tagPatternMatch.Success) { result.Parent = ObjectId.Parse(tagData, tagPatternMatch.Groups[1]); result.Author = module.ReEncodeStringFromLossless(tagPatternMatch.Groups[3].Value); result.TagName = tagPatternMatch.Groups[2].Value; result.Subject = result.TagName + ":" + tagPatternMatch.Groups[5].Value; result.Date = DateTimeUtils.ParseUnixTime(tagPatternMatch.Groups[4].Value); } } else if (objectType == LostObjectType.Blob) { var hash = objectId.ToString(); var blobPath = Path.Combine(module.WorkingDirGitDir, "objects", hash.Substring(0, 2), hash.Substring(2, ObjectId.GuidCharCount - 2)); result.Date = new FileInfo(blobPath).CreationTime; } return(result); string GetLostCommitLog() => VerifyHashAndRunCommand(LogCommandArgumentsFormat); string GetLostTagData() => VerifyHashAndRunCommand(TagCommandArgumentsFormat); string VerifyHashAndRunCommand(ArgumentString commandFormat) { return(module.GitExecutable.GetOutput(string.Format(commandFormat, objectId), outputEncoding: VsrModule.LosslessEncoding)); } LostObjectType GetObjectType(Group matchedGroup) { if (!matchedGroup.Success) { return(LostObjectType.Other); } switch (matchedGroup.Value) { case "commit": return(LostObjectType.Commit); case "blob": return(LostObjectType.Blob); case "tree": return(LostObjectType.Tree); case "tag": return(LostObjectType.Tag); default: return(LostObjectType.Other); } } }