-
Couldn't load subscription status.
- Fork 67
Add josh cli tool #1518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Add josh cli tool #1518
Conversation
8a2518e to
ffd2f6c
Compare
| let commits: Vec<git2::Commit> = changes | ||
| .iter() | ||
| .map(|(_, commit, _)| repo.find_commit(*commit).unwrap()) | ||
| .collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let commits: Vec<git2::Commit> = changes | |
| .iter() | |
| .map(|(_, commit, _)| repo.find_commit(*commit).unwrap()) | |
| .collect(); | |
| let commits: Vec<git2::Commit> = changes | |
| .iter() | |
| .map(|(_, commit, _)| repo.find_commit(*commit)) | |
| .collect::<Result<Vec<_>, _>>()?; |
|
|
||
| let mut trees: Vec<git2::Tree> = commits | ||
| .iter() | ||
| .map(|commit| commit.tree().unwrap()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above
| repo: &git2::Repository, | ||
| changes: &mut Vec<(String, git2::Oid, String)>, | ||
| base: git2::Oid, | ||
| ) -> JoshResult<()> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For CLI, we should consider using one of the more established error handling libraries, like miette or anyhow. They provide better means to present errors to users, with extra context etc.
|
|
||
| trees.insert(0, repo.find_commit(base)?.tree()?); | ||
|
|
||
| let diffs: Vec<git2::Diff> = (1..trees.len()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this tuple_windows?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or .windows(2) from standard library (although we already have itertools dep)
| .map(|commit| commit.tree().unwrap()) | ||
| .collect(); | ||
|
|
||
| trees.insert(0, repo.find_commit(base)?.tree()?); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can do
let base = std::iter::once(repo.find_commit(base)?.tree()?);
and then chain iterators
| let mut moved = std::collections::HashSet::new(); | ||
| let mut bases = vec![base]; | ||
| for _ in 0..changes.len() { | ||
| let mut new_bases = vec![]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kinda difficult to follow with all the mutability here -- perhaps some of these can be done iterator style?
| } | ||
|
|
||
| Ok(changes | ||
| .iter() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
into_iter()? changes vec isn't used anymore
| if seen.contains(&id) { | ||
| return Err(josh_error(&format!( | ||
| "rejecting to push {:?} with duplicate label", | ||
| change.commit | ||
| ))); | ||
| } | ||
| seen.push(id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for me this would be easier to read as folding on HashSet but up to you
| format!( | ||
| "refs/heads/@changes/{}/{}/{}", | ||
| baseref.replacen("refs/heads/", "", 1), | ||
| change.author, | ||
| change.id.as_ref().unwrap_or(&"".to_string()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would be cool to move it into a separate function to give all the different pieces meaningful names, be able to test it in unit tests, and to reuse this elsewhere if needed
| push_mode: PushMode, | ||
| baseref: &str, | ||
| author: &str, | ||
| ref_with_options: String, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it make sense for this also to be a &str? looks a bit weird that we're taking previous two by reference but move in this
| old: git2::Oid, | ||
| ) -> JoshResult<Vec<(String, git2::Oid, String)>> { | ||
| if let Some(changes) = changes { | ||
| let mut v = vec![]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not really a meaningful name
| if push_mode == PushMode::Split { | ||
| split_changes(repo, &mut v, old)?; | ||
| } | ||
| if push_mode == PushMode::Review { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
match?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: other files in the dir are named with underscores as opposed to dashes
| Command::Clone(args) => { | ||
| if let Err(e) = handle_clone(args) { | ||
| eprintln!("Error: {}", e); | ||
| std::process::exit(1); | ||
| } | ||
| } | ||
| Command::Fetch(args) => { | ||
| if let Err(e) = handle_fetch(args) { | ||
| eprintln!("Error: {}", e); | ||
| std::process::exit(1); | ||
| } | ||
| } | ||
| Command::Pull(args) => { | ||
| if let Err(e) = handle_pull(args) { | ||
| eprintln!("Error: {}", e); | ||
| std::process::exit(1); | ||
| } | ||
| } | ||
| Command::Push(args) => { | ||
| if let Err(e) = handle_push(args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Err() can/should move outside of match
| repo_shell: &Shell, | ||
| filter: &str, | ||
| remote_name: &str, | ||
| ) -> Result<(), Box<dyn std::error::Error>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see my other comment about error libraries -- this is anyhow/miette/color-eyre
| let original_dir = std::env::current_dir()?; | ||
| std::env::set_current_dir(repo_shell.cwd.as_path())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is super hacky -- why would we manipulate global state? repo_shell.cwd can be passed as arg pretty much anywhere?
josh-cli/src/bin/josh.rs
Outdated
| // Create filtered refs in refs/remotes/{remote_name}/* and refs/heads/* | ||
| //let mut head_branch_name = None; | ||
|
|
||
| //// First pass: find what HEAD points to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commented out code?
josh-cli/src/bin/josh.rs
Outdated
| } | ||
| } | ||
|
|
||
| // // Set HEAD to point to the default branch and checkout the working directory |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
commented out code
|
|
||
| // Change to the repository directory and add the remote using handle_remote_add | ||
| let original_dir = std::env::current_dir()?; | ||
| std::env::set_current_dir(&output_dir)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see other comment about set_current_dir
| fn handle_pull(args: &PullArgs) -> Result<(), Box<dyn std::error::Error>> { | ||
| // Check if we're in a git repository | ||
| let repo = | ||
| git2::Repository::open_from_env().map_err(|e| format!("Not in a git repository: {}", e))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it doesn't need to be from env here, it can be from path that we pass; we can figure out path at top level
josh-cli/src/bin/josh.rs
Outdated
| repo.set_head(&head_target) | ||
| .map_err(|e| format!("Failed to set HEAD: {}", e))?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we need crates mentioned above and/or thiserror crate for this
| }; | ||
|
|
||
| // Get PATH environment variable for shell commands | ||
| let path_env = std::env::var("PATH").unwrap_or_default(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what purpose does it serve?
77053c0 to
d860188
Compare
8d10bb4 to
3f3669d
Compare
Change: add-cli
3f3669d to
4ebd860
Compare
Change: add-cli