Skip to content

Commit

Permalink
completion: teach remote about existing names
Browse files Browse the repository at this point in the history
  • Loading branch information
senekor committed Nov 14, 2024
1 parent bfb7613 commit 966eeb9
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 2 deletions.
3 changes: 3 additions & 0 deletions cli/src/commands/bookmark/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::collections::HashSet;

use clap_complete::ArgValueCandidates;
use itertools::Itertools;
use jj_lib::git;
use jj_lib::revset::RevsetExpression;
Expand All @@ -24,6 +25,7 @@ use crate::cli_util::RevisionArg;
use crate::command_error::CommandError;
use crate::commit_templater::CommitTemplateLanguage;
use crate::commit_templater::RefName;
use crate::complete;
use crate::ui::Ui;

/// List bookmarks and their targets
Expand Down Expand Up @@ -57,6 +59,7 @@ pub struct BookmarkListArgs {
value_name = "REMOTE",
conflicts_with_all = ["all_remotes"],
value_parser = StringPattern::parse,
add = ArgValueCandidates::new(complete::git_remotes),
)]
remotes: Option<Vec<StringPattern>>,

Expand Down
8 changes: 7 additions & 1 deletion cli/src/commands/git/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use itertools::Itertools;
use jj_lib::repo::Repo;
use jj_lib::settings::ConfigResultExt as _;
Expand All @@ -21,6 +22,7 @@ use jj_lib::str_util::StringPattern;
use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::commands::git::get_single_remote;
use crate::complete;
use crate::git_util::get_git_repo;
use crate::git_util::git_fetch;
use crate::ui::Ui;
Expand All @@ -39,7 +41,11 @@ pub struct GitFetchArgs {
branch: Vec<StringPattern>,
/// The remote to fetch from (only named remotes are supported, can be
/// repeated)
#[arg(long = "remote", value_name = "REMOTE")]
#[arg(
long = "remote",
value_name = "REMOTE",
add = ArgValueCandidates::new(complete::git_remotes),
)]
remotes: Vec<String>,
/// Fetch from all remotes
#[arg(long, conflicts_with = "remotes")]
Expand Down
4 changes: 3 additions & 1 deletion cli/src/commands/git/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::io;
use std::io::Write;

use clap::ArgGroup;
use clap_complete::ArgValueCandidates;
use itertools::Itertools;
use jj_lib::backend::CommitId;
use jj_lib::git;
Expand Down Expand Up @@ -46,6 +47,7 @@ use crate::command_error::user_error;
use crate::command_error::user_error_with_hint;
use crate::command_error::CommandError;
use crate::commands::git::get_single_remote;
use crate::complete;
use crate::formatter::Formatter;
use crate::git_util::get_git_repo;
use crate::git_util::map_git_error;
Expand Down Expand Up @@ -76,7 +78,7 @@ use crate::ui::Ui;
#[command(group(ArgGroup::new("what").args(&["all", "deleted", "tracked"]).conflicts_with("specific")))]
pub struct GitPushArgs {
/// The remote to push to (only named remotes are supported)
#[arg(long)]
#[arg(long, add = ArgValueCandidates::new(complete::git_remotes))]
remote: Option<String>,
/// Push only this bookmark, or bookmarks matching a pattern (can be
/// repeated)
Expand Down
3 changes: 3 additions & 0 deletions cli/src/commands/git/remote/remove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use jj_lib::git;
use jj_lib::repo::Repo;

use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::complete;
use crate::git_util::get_git_repo;
use crate::ui::Ui;

/// Remove a Git remote and forget its bookmarks
#[derive(clap::Args, Clone, Debug)]
pub struct GitRemoteRemoveArgs {
/// The remote's name
#[arg(add = ArgValueCandidates::new(complete::git_remotes))]
remote: String,
}

Expand Down
3 changes: 3 additions & 0 deletions cli/src/commands/git/remote/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use jj_lib::git;
use jj_lib::repo::Repo;

use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::complete;
use crate::git_util::get_git_repo;
use crate::ui::Ui;

/// Rename a Git remote
#[derive(clap::Args, Clone, Debug)]
pub struct GitRemoteRenameArgs {
/// The name of an existing remote
#[arg(add = ArgValueCandidates::new(complete::git_remotes))]
old: String,
/// The desired name for `old`
new: String,
Expand Down
3 changes: 3 additions & 0 deletions cli/src/commands/git/remote/set_url.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use clap_complete::ArgValueCandidates;
use jj_lib::git;
use jj_lib::repo::Repo;

use crate::cli_util::CommandHelper;
use crate::command_error::CommandError;
use crate::complete;
use crate::git_util::get_git_repo;
use crate::ui::Ui;

/// Set the URL of a Git remote
#[derive(clap::Args, Clone, Debug)]
pub struct GitRemoteSetUrlArgs {
/// The remote's name
#[arg(add = ArgValueCandidates::new(complete::git_remotes))]
remote: String,
/// The desired url for `remote`
url: String,
Expand Down
19 changes: 19 additions & 0 deletions cli/src/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,25 @@ pub fn local_bookmarks() -> Vec<CompletionCandidate> {
})
}

pub fn git_remotes() -> Vec<CompletionCandidate> {
with_jj(|mut jj| {
let output = jj
.arg("git")
.arg("remote")
.arg("list")
.output()
.map_err(user_error)?;

let stdout = String::from_utf8_lossy(&output.stdout);

Ok(stdout
.lines()
.filter_map(|line| line.split_once(' ').map(|(name, _url)| name))
.map(CompletionCandidate::new)
.collect())
})
}

/// Shell out to jj during dynamic completion generation
///
/// In case of errors, print them and early return an empty vector.
Expand Down
49 changes: 49 additions & 0 deletions cli/tests/test_completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,52 @@ fn test_completions_are_generated() {
let stdout = test_env.jj_cmd_success(test_env.env_root(), &["--"]);
assert!(stdout.starts_with("complete --keep-order --exclusive --command jj --arguments"));
}

#[test]
fn test_remote_names() {
let mut test_env = TestEnvironment::default();
test_env.jj_cmd_ok(test_env.env_root(), &["git", "init"]);

test_env.jj_cmd_ok(
test_env.env_root(),
&["git", "remote", "add", "origin", "[email protected]:user/repo"],
);

test_env.add_env_var("COMPLETE", "fish");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "git", "remote", "remove", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "git", "remote", "rename", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "git", "remote", "set-url", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "git", "push", "--remote", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "git", "fetch", "--remote", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");

let stdout = test_env.jj_cmd_success(
test_env.env_root(),
&["--", "jj", "bookmark", "list", "--remote", "o"],
);
insta::assert_snapshot!(stdout, @r"origin");
}

0 comments on commit 966eeb9

Please sign in to comment.