// // Creates a new log file and returns the path // private static string GenerateLogMessage(Review.Review.Properties properties, string reviewUrl, Logging logger) { // Get the temp file string logFile = Path.GetTempFileName(); using (StreamWriter sw = new StreamWriter(logFile)) { // Write our log to the file if (string.IsNullOrWhiteSpace(properties.Summary) == false) { sw.WriteLine(properties.Summary + "\n"); } if (string.IsNullOrWhiteSpace(properties.Description) == false) { sw.WriteLine(properties.Description + "\n"); } // Post the Jira state to this commit string jiraState = BuildJiraLogContent(properties.JiraId); sw.WriteLine(jiraState); // Post the review state to this commit sw.WriteLine(ReviewState_Tag, properties.ReviewLevel.GetSplitName(), reviewUrl == null ? string.Empty : reviewUrl.Replace("diff/", "")); // Add a tag identifying what it was generated by sw.WriteLine("\n* Commit log generated by '{0}' v{1}", "Reviewboard Integration Tools", RB_Tools.Shared.Utilities.Version.VersionNumber); } // Return the log file logger.Log("Log file generated - {0}", logFile); return(logFile); }
// // Opens a new commit dialog with the given options // public static void OpenCommitDialog(Review.Review.Properties properties, string reviewUrl, Logging logger) { string logFile = GenerateLogMessage(properties, reviewUrl, logger); OpenTortoiseSVN(properties.Contents.Files, properties.Path, logFile, logger); AddLogMessageToJiraTicket(properties.JiraId, logFile, logger); // Clean up CleanUpTemporaryFiles(logFile, logger); }
// Constructor public ReviewRequestProperties(Review.Review.Properties reviewProperties, string workingCopy) { ReviewProperties = reviewProperties; WorkingCopy = workingCopy; }
// // Starts a review // private void button_CreateReview_Click(object sender, EventArgs e) { // We need a sumary before we raise the review if (string.IsNullOrWhiteSpace(textBox_Summary.Text) == true) { MessageBox.Show(this, "You need to provide a summary before you can post a review", "Unable to post review", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Do we need a Jira ticket? if (Settings.Settings.Default.JiraRequired == true) { if (string.IsNullOrWhiteSpace(textBox_JiraId.Text) == true) { MessageBox.Show(this, "You need to provide a Jira ticket before you can continue", "Unable to post review", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } } // Only bother checking against the reviewboard server if we are doing a review RB_Tools.Shared.Review.Properties.Level reviewLevel = (RB_Tools.Shared.Review.Properties.Level)comboBox_ReviewLevel.SelectedIndex; if (reviewLevel == RB_Tools.Shared.Review.Properties.Level.FullReview) { string reviewboardServer = Names.Url[(int)Names.Type.Reviewboard]; if (Credentials.Available(reviewboardServer) == false) { m_logger.Log("Requesting Reviewboard credentials"); DialogResult dialogResult = MessageBox.Show(this, "You must be authenticated with the Reviewboard server before generating a review.\n\nDo you want to authenticate now?", "Authentication Error", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (dialogResult == DialogResult.Yes) { RB_Tools.Shared.Authentication.Targets.Reviewboard.Authenticate(m_logger); } // Check if we're still unauthenticated if (Credentials.Available(reviewboardServer) == false) { m_logger.Log("Credentials still unavailable"); return; } } } // Check Jira authentication if needed if (string.IsNullOrWhiteSpace(textBox_JiraId.Text) == false) { string jiraServer = Names.Url[(int)Names.Type.Jira]; if (Credentials.Available(jiraServer) == false) { m_logger.Log("Requesting Jira credentials"); DialogResult dialogResult = MessageBox.Show(this, "You must be authenticated with the Jira server before continuing.\n\nDo you want to authenticate now?", "Authentication Error", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (dialogResult == DialogResult.Yes) { RB_Tools.Shared.Authentication.Targets.Jira.Authenticate(m_logger); } // Check if we're still unauthenticated if (Credentials.Available(jiraServer) == false) { m_logger.Log("Credentials still unavailable"); return; } } } // Save the state of our review groups SaveSelectedReviewGroups(); // Update our state UpdateCreateReviewDialogState(State.PostReview); // Do we need to keep our artifacts? if (checkBox_KeepArtifacts.Checked == true) { Utilities.Storage.KeepAssets(textBox_Summary.Text, m_logger); } Utilities.Storage.Keep(m_originalRequest, "Original File List.txt", false, m_logger); // Build up the list of review groups List <string> selectedReviewGroups = new List <string>(); foreach (int thisIndex in checkedListBox_ReviewGroups.CheckedIndices) { Reviewboard.ReviewGroup thisGroup = m_reviewGroups[thisIndex]; selectedReviewGroups.Add(thisGroup.InternalName); } // Build up the properties of this review Review.Review.Properties reviewProperties = new Review.Review.Properties( m_requestDirectory, m_reviewSource, textBox_ReviewId.Text, textBox_Summary.Text, textBox_Description.Text, textBox_Testing.Text, textBox_JiraId.Text.Trim().Replace(" ", ""), selectedReviewGroups, reviewLevel, checkBox_CopiesAsAdds.Checked ); // Trigger the correct state depending on whether we are reviewing TriggerReviewRequest(reviewProperties); }
// // Runs the review request // private void TriggerReviewRequest(Review.Review.Properties reviewProperties) { m_logger.Log("Triggering review request"); // Build up the background work BackgroundWorker updateThread = new BackgroundWorker(); // Called when we need to trigger the request updateThread.DoWork += (object objectSender, DoWorkEventArgs args) => { // Pull out the properties of the request ReviewRequestProperties thisRequest = args.Argument as ReviewRequestProperties; OutputRequestProperties(thisRequest); // Do we need to validate the Jira ticket? bool ticketValid = ValidateJiraTicket(thisRequest.ReviewProperties.JiraId); if (ticketValid == false) { args.Result = new Reviewboard.ReviewRequestResult(null, "Unable to validate the given Jira ticket", thisRequest.ReviewProperties); return; } // Carry out the review args.Result = RequestReview(thisRequest); }; // Called when the thread is complete updateThread.RunWorkerCompleted += (object objectSender, RunWorkerCompletedEventArgs args) => { // Check if we had an error if (args.Error != null) { m_logger.Log("Error raised during review request - {0}", args.Error.Message); string body = string.Format("Exception thrown when trying to raise a new review\n\nException: {0}\n\nDescription: {1}", args.Error.GetType().Name, args.Error.Message); // Was it an authentication error? bool authenticationRequired = false; if (args.Error.Message.Contains("username or password was not correct") == true) { authenticationRequired = true; body += "\n\nDo you want to attempt to reauthenticate with the server?"; } // Show the options MessageBoxButtons buttonTypes = (authenticationRequired == true ? MessageBoxButtons.YesNo : MessageBoxButtons.OK); DialogResult result = MessageBox.Show(this, body, @"Unable to raise review", buttonTypes, MessageBoxIcon.Error); // Continue? if (result == DialogResult.Yes && authenticationRequired == true) { RB_Tools.Shared.Authentication.Targets.Reviewboard.Authenticate(m_logger); } OnReviewFinished(FinishReason.Error); } else { // Pull out the results of the review Reviewboard.ReviewRequestResult requestResult = args.Result as Reviewboard.ReviewRequestResult; // If we don't have a review URL, we failed if (string.IsNullOrWhiteSpace(requestResult.Error) == false) { m_logger.Log("Error raised during review request - {0}", requestResult.Error); // Raise the error and we're done MessageBox.Show(this, requestResult.Error, @"Unable to raise review", MessageBoxButtons.OK, MessageBoxIcon.Error); OnReviewFinished(FinishReason.Error); } else { if (requestResult.Properties.ReviewLevel == RB_Tools.Shared.Review.Properties.Level.FullReview) { m_logger.Log("Review posted successful - {0}", requestResult.Url); } // Open the browser, doing this manually so we can open on the diff if (string.IsNullOrWhiteSpace(requestResult.Url) == false) { System.Diagnostics.Process.Start(requestResult.Url); } // If it's just a patch file, we don't need to do anything else if (m_reviewSource.Source == Review.Review.Source.Patch) { m_logger.Log("Patch review completed, process finished"); OnReviewFinished(FinishReason.Success); } else { m_logger.Log("File review finished, moving onto next stage"); // Flag the actual review as done so we lose the path file // and then it doesn't show up in TortoiseSVN OnReviewFinished(FinishReason.Interim); TriggerTortoiseRequest(requestResult); } } } }; // Kick off the request ReviewRequestProperties requestProperties = new ReviewRequestProperties(reviewProperties, m_requestDirectory); updateThread.RunWorkerAsync(requestProperties); }
// Constructor public ReviewRequestResult(string reviewUrl, string reviewError, Review.Review.Properties reviewRequest) { Url = reviewUrl; Error = reviewError; Properties = reviewRequest; }
// // Raises a new review // public static ReviewRequestResult RequestReview(string workingDirectory, string server, string username, string password, Review.Review.Properties reviewProperties, Logging logger) { // We may not need to generate a review if (reviewProperties.ReviewLevel != RB_Tools.Shared.Review.Properties.Level.FullReview) { // No review needed so exit logger.Log("Ignoring review request as a full review was not requested"); return(new ReviewRequestResult(string.Empty, string.Empty, reviewProperties)); } // Read out the description and testing into a temp file string descriptionFile = GetFileWithContents(reviewProperties.Description, reviewProperties.Summary); string testingFile = GetFileWithContents(reviewProperties.Testing, null); // Build up the review command string commandProperties = string.Format("--server {0} --summary \"{1}\" ", server, reviewProperties.Summary); if (string.IsNullOrWhiteSpace(descriptionFile) == false) { commandProperties += string.Format("--description-file \"{0}\" ", descriptionFile); } if (string.IsNullOrWhiteSpace(testingFile) == false) { commandProperties += string.Format("--testing-done-file \"{0}\" ", testingFile); } if (string.IsNullOrWhiteSpace(reviewProperties.JiraId) == false) { string formattedJiraIds = BuildJiraLinks(reviewProperties.JiraId); commandProperties += string.Format("--bugs-closed \"{0}\" ", formattedJiraIds); } // Options commandProperties += string.Format("--svn-show-copies-as-adds={0} ", reviewProperties.CopiesAsAdds == true ? "y":"n"); // Build up the review groups if (reviewProperties.Groups.Count != 0) { string reviewGroups = reviewProperties.Groups[0]; for (int i = 1; i < reviewProperties.Groups.Count; ++i) { reviewGroups += "," + reviewProperties.Groups[i]; } // Add the command commandProperties += string.Format("--target-groups \"{0}\" ", reviewGroups); } // Get the name of the branch we're on string branchUrl = Svn.GetBranch(workingDirectory); if (string.IsNullOrWhiteSpace(branchUrl) == false) { commandProperties += string.Format("--branch \"{0}\" ", branchUrl); } // Update an existing review? if (string.IsNullOrWhiteSpace(reviewProperties.ReviewId) == false) { commandProperties += string.Format("--review-request-id \"{0}\" ", reviewProperties.ReviewId); } // Pass through the patch file we generated or used commandProperties += string.Format("--diff-filename \"{0}\" ", reviewProperties.Contents.Patch); // Build up the command string commandOptions = string.Format(@"post {0}", commandProperties); string rbtPath = RB_Tools.Shared.Targets.Reviewboard.Path(); logger.Log("Requesting review"); logger.Log("* Calling {0} {1}", rbtPath, commandOptions); // Run the process Process.Output output = Process.Start(workingDirectory, rbtPath, commandOptions); // Throw to return the error if (string.IsNullOrWhiteSpace(output.StdErr) == false) { logger.Log("Error raised when requesting review - {0}", output.StdErr); throw new ApplicationException(output.StdErr); } // Break up the results string[] outputLines = output.StdOut.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); // Pull out the link to the review (use the diff) string reviewUrl = string.Empty; if (outputLines.Length >= 3) { reviewUrl = outputLines[2]; } // Review URL needs to reference the reviewboard server string reviewError = null; if (reviewUrl.ToLower().Contains(server.ToLower()) == false) { reviewError = output.StdOut; } // Lose the temp files if we have them CleanUpTemporaryFiles(descriptionFile, testingFile, logger); // Return the results return(new ReviewRequestResult(reviewUrl, reviewError, reviewProperties)); }