Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,6 @@ mouse = true
leader = ";" # configurable prefix for leader shortcuts
comment_vim = false # vim modal editing in the review comment box
relative_line_numbers = false # show rendered-row distances in the diff gutter
review_watch_interval_ms = 1000 # set to 0 to disable persisted-review polling
diff_watch_interval_ms = 0 # set above 0 to auto-reload the local diff

[[comment_types]]
id = "issue"
Expand Down
4 changes: 4 additions & 0 deletions docs/CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ theme_light = "gruvbox-light"
diff_view = "side-by-side"
ignore_whitespace = false
show_file_list = true
show_pr_checks = false
show_pr_comments = true
mouse = true
leader = ","
comment_vim = false
Expand Down Expand Up @@ -78,6 +80,8 @@ legend = true
| `initial_commit_selection` | `all` | Which commits are selected when a multi-commit review first opens: `all`, or `oldest` to start on just the oldest commit and walk forward with `(` / `)`. |
| `ignore_whitespace` | `false` | Ignore all whitespace in local Git, jj, and hg diffs. PR diffs are unchanged. |
| `show_file_list` | `true` | Whether the file list panel is visible on startup. Toggle with `<leader>e`. |
| `show_pr_checks` | `false` | Whether PR CI checks are fetched and shown. Set to `true` to include GitHub check rollups. |
| `show_pr_comments` | `true` | Whether PR conversation comments are fetched and shown. Set to `false` to skip PR comments. |
| `show_commits` | `true` | Whether the inline commit selector pane is visible on startup for multi-commit reviews. Toggle with `<leader>s` or `:set commits!`. |
| `mouse` | `true` | Wheel scrolling, clicks, and drag-to-select. |
| `leader` | `;` | Single-character prefix for panel focus, sidebar toggles, and review-comment shortcuts. Invalid multi-character values are ignored with a startup warning. |
Expand Down
46 changes: 44 additions & 2 deletions src/app/init.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use super::*;

#[derive(Clone, Copy)]
struct PrDisplayOptions {
show_checks: bool,
show_comments: bool,
}

impl App {
pub fn new(
theme: Theme,
Expand All @@ -11,13 +17,17 @@ impl App {
// selector. Errors here surface before TUI startup like other
// startup failures.
if let Some(target) = options.pr_target {
return Self::new_from_pr_target(
return Self::new_from_pr_target_with_pr_display_options(
theme,
comment_type_configs,
output_to_stdout,
target,
options.repo_url_override.clone(),
options.commit_selection,
PrDisplayOptions {
show_checks: options.show_pr_checks,
show_comments: options.show_pr_comments,
},
);
}

Expand Down Expand Up @@ -535,6 +545,8 @@ impl App {
pr_submit_rx: None,
current_pr_head: None,
pr_info: None,
show_pr_checks: false,
show_pr_comments: true,
should_quit: false,
dirty: false,
quit_warned: false,
Expand Down Expand Up @@ -777,6 +789,29 @@ impl App {
target: &str,
repo_url_override: Option<ForgeRepository>,
commit_selection: CommitSelectionStart,
) -> Result<Self> {
Self::new_from_pr_target_with_pr_display_options(
theme,
comment_type_configs,
output_to_stdout,
target,
repo_url_override,
commit_selection,
PrDisplayOptions {
show_checks: false,
show_comments: true,
},
)
}

fn new_from_pr_target_with_pr_display_options(
theme: Theme,
comment_type_configs: Option<Vec<CommentTypeConfig>>,
output_to_stdout: bool,
target: &str,
repo_url_override: Option<ForgeRepository>,
commit_selection: CommitSelectionStart,
display_options: PrDisplayOptions,
) -> Result<Self> {
use crate::forge::azure::az::parse_pull_request_target_azure;
use crate::forge::bitbucket::bkt::parse_pull_request_target_bitbucket;
Expand Down Expand Up @@ -844,7 +879,12 @@ impl App {
.as_deref()
.and_then(|root| crate::forge::local_checkout_for_repo(root, &target_repo));

let backend = create_forge_backend(&target_repo, local_checkout_for_target.clone());
let backend = create_forge_backend(
&target_repo,
local_checkout_for_target.clone(),
display_options.show_checks,
display_options.show_comments,
);
let highlighter = theme.syntax_highlighter();
let opened = open_pull_request(
backend.as_ref(),
Expand Down Expand Up @@ -885,6 +925,8 @@ impl App {
None,
repo_url_override,
)?;
app.show_pr_checks = display_options.show_checks;
app.show_pr_comments = display_options.show_comments;

// Wire the forge backend so context expansion routes through it.
app.forge_backend = Some(backend);
Expand Down
19 changes: 18 additions & 1 deletion src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,19 @@ pub const GAP_EXPAND_BATCH: usize = 20;
fn create_forge_backend(
repo: &ForgeRepository,
local_checkout: Option<PathBuf>,
show_pr_checks: bool,
show_pr_comments: bool,
) -> Box<dyn ForgeBackend> {
use crate::forge::traits::ForgeKind;
match repo.kind {
ForgeKind::GitHub => {
use crate::forge::github::gh::GitHubGhBackend;
Box::new(GitHubGhBackend::new(Some(repo.clone())).with_local_checkout(local_checkout))
Box::new(
GitHubGhBackend::new(Some(repo.clone()))
.with_local_checkout(local_checkout)
.with_pr_checks(show_pr_checks)
.with_pr_comments(show_pr_comments),
)
}
ForgeKind::GitLab => {
use crate::forge::gitlab::GitLabGlabBackend;
Expand Down Expand Up @@ -1267,6 +1274,12 @@ pub struct App {
pub current_pr_head: Option<String>,
/// Extended PR metadata rendered at the top of the diff view. Populated in PR mode.
pub pr_info: Option<crate::forge::traits::PullRequestInfo>,
/// Whether pull-request CI checks are fetched and rendered. Defaults to
/// false; configured before the first direct PR load.
pub show_pr_checks: bool,
/// Whether pull-request conversation comments are fetched and rendered.
/// Defaults to true; configured before the first direct PR load.
pub show_pr_comments: bool,

pub should_quit: bool,
pub dirty: bool,
Expand Down Expand Up @@ -1659,6 +1672,10 @@ pub struct AppStartupOptions<'a> {
/// Whole-repo annotation mode (`--all-files`). Mutually exclusive with
/// the other selectors; the binary validates that before reaching here.
pub all_files: bool,
/// Whether pull-request CI checks are fetched and rendered.
pub show_pr_checks: bool,
/// Whether pull-request conversation comments are fetched and rendered.
pub show_pr_comments: bool,
pub git_backend_preference: GitBackendPreference,
pub diff_whitespace_mode: DiffWhitespaceMode,
/// Which commits are selected when a multi-commit review first opens.
Expand Down
73 changes: 58 additions & 15 deletions src/app/pr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,15 @@ impl App {
let pr_number = current.key.number;
let head_sha = current.key.head_sha.clone();
let base_sha = current.base_sha.clone();
let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;
std::thread::spawn(move || {
let backend = create_forge_backend(&repository, local_checkout);
let backend = create_forge_backend(
&repository,
local_checkout,
show_pr_checks,
show_pr_comments,
);
let details = crate::forge::traits::PullRequestDetails {
repository: repository.clone(),
number: pr_number,
Expand Down Expand Up @@ -481,8 +488,15 @@ impl App {

let repository = current.key.repository.clone();
let pr_number = current.key.number;
let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;
std::thread::spawn(move || {
let backend = create_forge_backend(&repository, local_checkout);
let backend = create_forge_backend(
&repository,
local_checkout,
show_pr_checks,
show_pr_comments,
);
let target =
PullRequestTarget::with_repository(repository, pr_number, pr_number.to_string());
let outcome = fetch_pr_data(backend.as_ref(), target).map_err(|e| e.to_string());
Expand Down Expand Up @@ -563,7 +577,12 @@ impl App {
if head_changed {
let details_for_threads = opened.details.clone();
let opened = self.opened_pr_with_new_head_session(opened)?;
let backend = create_forge_backend(&request.repository, local_checkout.clone());
let backend = create_forge_backend(
&request.repository,
local_checkout.clone(),
self.show_pr_checks,
self.show_pr_comments,
);
let previous_message = self.message.clone();
self.enter_pr_diff_mode(backend, opened)?;
self.spawn_pr_threads_fetch(&details_for_threads, local_checkout);
Expand Down Expand Up @@ -618,7 +637,12 @@ impl App {
.forge_backend
.as_deref()
.and_then(|backend| backend.local_checkout_path());
let backend = create_forge_backend(&current.key.repository, local_checkout.clone());
let backend = create_forge_backend(
&current.key.repository,
local_checkout.clone(),
self.show_pr_checks,
self.show_pr_comments,
);
self.reload_pull_request_with_backend(backend, local_checkout)
}

Expand Down Expand Up @@ -706,6 +730,8 @@ impl App {
let (tx, rx) = std::sync::mpsc::channel();
self.pr_load_rx = Some(rx);

let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;
std::thread::spawn(move || {
// Canonical resolution (fork parent lookup) is GitHub-only.
let canonical = if skip_resolution || origin.kind != ForgeKind::GitHub {
Expand All @@ -716,7 +742,7 @@ impl App {
let runner = SystemGhRunner;
resolve_canonical_repository(&origin, override_repo.as_ref(), &runner)
};
let backend = create_forge_backend(&canonical, None);
let backend = create_forge_backend(&canonical, None, show_pr_checks, show_pr_comments);
let query =
PullRequestListQuery::first_page_with_scope(canonical.clone(), PR_PAGE_SIZE, scope);
let result = backend
Expand All @@ -740,8 +766,10 @@ impl App {
let (tx, rx) = std::sync::mpsc::channel();
self.pr_load_rx = Some(rx);

let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;
std::thread::spawn(move || {
let backend = create_forge_backend(&repository, None);
let backend = create_forge_backend(&repository, None, show_pr_checks, show_pr_comments);
let query = PullRequestListQuery {
repository,
already_loaded,
Expand Down Expand Up @@ -857,16 +885,19 @@ impl App {

let summary_repo = summary.repository.clone();
let pr_number = summary.number;
// Resolve the local checkout up front (git remote read, cheap) so the
// diff-fetching backend can use it. Azure DevOps sources its diff from
// a local clone; without this it errors with "needs a local clone" even
// when tuicr is launched from inside the clone. GitHub/GitLab ignore
// the checkout for diffs, so this only ever helps. Mirrors the CLI path
// (`new_from_pr_target`) and `finish_pr_open`.
// Resolve the local checkout up front so Azure DevOps can source its
// diff from the clone when opening a PR from the selector.
let local_checkout =
crate::forge::local_checkout_for_repo(&self.vcs_info.root_path, &summary.repository);
let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;
std::thread::spawn(move || {
let backend = create_forge_backend(&summary_repo, local_checkout);
let backend = create_forge_backend(
&summary_repo,
local_checkout,
show_pr_checks,
show_pr_comments,
);
let target =
PullRequestTarget::with_repository(summary_repo, pr_number, pr_number.to_string());
let outcome = fetch_pr_data(backend.as_ref(), target).map_err(|e| e.to_string());
Expand Down Expand Up @@ -956,7 +987,12 @@ impl App {
highlighter,
)?;
let opened = Self::opened_pr_with_persisted_session(opened)?;
let backend = create_forge_backend(&request.repository, local_checkout.clone());
let backend = create_forge_backend(
&request.repository,
local_checkout.clone(),
self.show_pr_checks,
self.show_pr_comments,
);
let previous_message = self.message.clone();
self.enter_pr_diff_mode(backend, opened)?;
// Kick the remote-thread fetch off on a fresh background thread.
Expand Down Expand Up @@ -990,9 +1026,16 @@ impl App {
let repository = details.repository.clone();
let pr_number = details.number;
let head_sha = details.head_sha.clone();
let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;

std::thread::spawn(move || {
let backend = create_forge_backend(&repository, local_checkout);
let backend = create_forge_backend(
&repository,
local_checkout,
show_pr_checks,
show_pr_comments,
);
let threads = backend
.list_review_threads(&details_clone)
.map_err(|e| e.to_string());
Expand Down
9 changes: 8 additions & 1 deletion src/app/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -349,9 +349,16 @@ impl App {
let event = in_flight.event;
let mappable = in_flight.mappable.clone();
let commit_id = state.commit_id.clone();
let show_pr_checks = self.show_pr_checks;
let show_pr_comments = self.show_pr_comments;

std::thread::spawn(move || {
let backend = create_forge_backend(&repository, local_checkout);
let backend = create_forge_backend(
&repository,
local_checkout,
show_pr_checks,
show_pr_comments,
);
// Need PR details for repo/owner routing; refetch lightly via
// the same target the user opened with.
let target = PullRequestTarget::with_repository(
Expand Down
Loading
Loading