예제 #1
0
        /// <summary>
        /// Attempts to parse the results indicating that further testing is required and that the
        /// repository has now been updated to a new revision for testing and subsequent marking of
        /// good or bad.
        /// </summary>
        /// <param name="standardOutput">
        /// The standard output from executing the command.
        /// </param>
        /// <returns>
        /// <c>true</c> if this method was able to parse the results correctly;
        /// otherwise <c>false</c> to continue testing other ways to parse it.
        /// </returns>
        private bool ParseTestingResult(string standardOutput)
        {
            var   re = new Regex(@"^Testing changeset (?<revno>\d+):", RegexOptions.IgnoreCase);
            Match ma = re.Match(standardOutput);

            if (ma.Success)
            {
                int currentlyAtRevision = int.Parse(ma.Groups["revno"].Value, CultureInfo.InvariantCulture);
                Result = new BisectResult(RevSpec.Single(currentlyAtRevision), false);
            }

            return(ma.Success);
        }
예제 #2
0
        /// <summary>
        /// Attempts to parse the results that indicate that the first good changeset was found.
        /// </summary>
        /// <param name="standardOutput">
        /// The standard output from executing the command.
        /// </param>
        /// <returns>
        /// <c>true</c> if this method was able to parse the results correctly;
        /// otherwise <c>false</c> to continue testing other ways to parse it.
        /// </returns>
        private bool ParseFoundResult(string standardOutput)
        {
            var   re = new Regex(@"^The first good revision is:\s+changeset:\s+(?<revno>\d+):", RegexOptions.IgnoreCase);
            Match ma = re.Match(standardOutput);

            if (ma.Success)
            {
                int foundAtRevision = int.Parse(ma.Groups["revno"].Value, CultureInfo.InvariantCulture);
                Result = new BisectResult(RevSpec.Single(foundAtRevision), true);
            }

            return(ma.Success);
        }
예제 #3
0
        /// <summary>
        /// This method should parse and store the appropriate execution result output
        /// according to the type of data the command line client would return for
        /// the command.
        /// </summary>
        /// <param name="exitCode">
        /// The exit code from executing the command line client.
        /// </param>
        /// <param name="standardOutput">
        /// The standard output from executing the command line client.
        /// </param>
        /// <remarks>
        /// Note that as long as you descend from <see cref="MercurialCommandBase{T}"/> you're not required to call
        /// the base method at all.
        /// </remarks>
        protected override void ParseStandardOutputForResults(int exitCode, string standardOutput)
        {
            if (exitCode != 0)
            {
                return;
            }

            Match ma = Regex.Match(standardOutput, @"^(?<hash>[a-f0-9]{12,40}).*$", RegexOptions.IgnoreCase);

            if (ma.Success)
            {
                Result = RevSpec.Single(ma.Groups["hash"].Value);
            }
        }
예제 #4
0
        /// <summary>
        /// This method should parse and store the appropriate execution result output
        /// according to the type of data the command line client would return for
        /// the command.
        /// </summary>
        /// <param name="exitCode">
        /// The exit code from executing the command line client.
        /// </param>
        /// <param name="standardOutput">
        /// The standard output from executing the command line client.
        /// </param>
        /// <remarks>
        /// Note that as long as you descend from <see cref="MercurialCommandBase{T}"/> you're not required to call
        /// the base method at all.
        /// </remarks>
        protected override void ParseStandardOutputForResults(int exitCode, string standardOutput)
        {
            base.ParseStandardOutputForResults(exitCode, standardOutput);
            var re = new Regex(@"^committed\s+changeset\s+\d+:(?<hash>[0-9a-f]{40})$", RegexOptions.IgnoreCase);

            foreach (Match ma in standardOutput.Split(
                         new[]
            {
                '\n', '\r'
            }, StringSplitOptions.RemoveEmptyEntries).Select(line => re.Match(line)).Where(ma => ma.Success))
            {
                Result = RevSpec.Single(ma.Groups["hash"].Value);
                return;
            }

            Result = null;
        }
예제 #5
0
        /// <summary>
        /// Parse the given XML lazily and return a collection of <see cref="Changeset"/>
        /// objects for the information contained in it, in the order the changesets
        /// appear in the xml.
        /// </summary>
        /// <param name="xml">
        /// The XML to parse.
        /// </param>
        /// <returns>
        /// A collection of <see cref="Changeset"/> objects.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">
        /// <para>An unknown path action character was detected in the log output.</para>
        /// <para>- or -</para>
        /// <para>The XML content was not legal according to the expected format.</para>
        /// </exception>
        public static IEnumerable <Changeset> LazyParse(string xml)
        {
            if (StringEx.IsNullOrWhiteSpace(xml))
            {
                yield break;
            }

            var serializer = new XmlSerializer(typeof(LogEntryNode));

            foreach (string entryXml in LazyExtractChangesetXmlPieces(xml))
            {
                var entry     = (LogEntryNode)serializer.Deserialize(new StringReader(entryXml));
                var changeset = new Changeset
                {
                    Timestamp          = entry.Timestamp,
                    AuthorName         = (entry.Author ?? new LogEntryAuthorNode()).Name,
                    AuthorEmailAddress = (entry.Author ?? new LogEntryAuthorNode()).Email,
                    CommitMessage      = entry.CommitMessage ?? string.Empty,
                    Branch             = entry.Branch ?? "default",
                    Hash           = entry.Hash,
                    RevisionNumber = entry.Revision,
                    Revision       = RevSpec.Single(entry.Hash),
                    Tags           = entry.Tags.Select(t => t.Name).ToArray(),
                };

                switch (entry.Parents.Count)
                {
                case 2:
                    changeset.RightParentHash     = entry.Parents[1].Hash;
                    changeset.RightParentRevision = entry.Parents[1].Revision;
                    goto case 1;

                case 1:
                    changeset.LeftParentHash     = entry.Parents[0].Hash;
                    changeset.LeftParentRevision = entry.Parents[0].Revision;
                    break;

                case 0:
                    changeset.LeftParentRevision = changeset.RevisionNumber - 1;
                    break;
                }

                foreach (LogEntryPathNode action in entry.PathActions)
                {
                    var pathAction = new ChangesetPathAction
                    {
                        Path = action.Path,
                    };
                    switch (action.Action)
                    {
                    case "M":
                        pathAction.Action = ChangesetPathActionType.Modify;
                        break;

                    case "A":
                        pathAction.Action = ChangesetPathActionType.Add;
                        LogEntryCopyNode copySource = entry.Copies.Where(c => c.Destination == action.Path).FirstOrDefault();
                        if (copySource != null)
                        {
                            pathAction.Source = copySource.Source;
                        }
                        break;

                    case "R":
                        pathAction.Action = ChangesetPathActionType.Remove;
                        break;

                    default:
                        throw new InvalidOperationException("Unknown path action: " + action.Action);
                    }
                    changeset.PathActions.Add(pathAction);
                }

                yield return(changeset);
            }
        }