Skip to content

Conversation

@christian-schilling
Copy link
Member

Change: add-cli

@christian-schilling christian-schilling force-pushed the @changes/master/christian.schilling.de@gmail.com/add-cli branch 4 times, most recently from 8a2518e to ffd2f6c Compare October 10, 2025 17:30
Comment on lines +52 to +55
let commits: Vec<git2::Commit> = changes
.iter()
.map(|(_, commit, _)| repo.find_commit(*commit).unwrap())
.collect();
Copy link
Collaborator

@vlad-ivanov-name vlad-ivanov-name Oct 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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())
Copy link
Collaborator

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<()> {
Copy link
Collaborator

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())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this tuple_windows?

Copy link
Collaborator

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()?);
Copy link
Collaborator

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![];
Copy link
Collaborator

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()
Copy link
Collaborator

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

Comment on lines +130 to +136
if seen.contains(&id) {
return Err(josh_error(&format!(
"rejecting to push {:?} with duplicate label",
change.commit
)));
}
seen.push(id);
Copy link
Collaborator

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

Comment on lines +149 to +153
format!(
"refs/heads/@changes/{}/{}/{}",
baseref.replacen("refs/heads/", "", 1),
change.author,
change.id.as_ref().unwrap_or(&"".to_string()),
Copy link
Collaborator

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,
Copy link
Collaborator

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![];
Copy link
Collaborator

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

Comment on lines +180 to +183
if push_mode == PushMode::Split {
split_changes(repo, &mut v, old)?;
}
if push_mode == PushMode::Review {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

match?

Copy link
Collaborator

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

Comment on lines +210 to +252
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) {
Copy link
Collaborator

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>> {
Copy link
Collaborator

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

Comment on lines +256 to +280
let original_dir = std::env::current_dir()?;
std::env::set_current_dir(repo_shell.cwd.as_path())?;
Copy link
Collaborator

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?

// Create filtered refs in refs/remotes/{remote_name}/* and refs/heads/*
//let mut head_branch_name = None;

//// First pass: find what HEAD points to
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

commented out code?

}
}

// // Set HEAD to point to the default branch and checkout the working directory
Copy link
Collaborator

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)?;
Copy link
Collaborator

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))?;
Copy link
Collaborator

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

Comment on lines 440 to 441
repo.set_head(&head_target)
.map_err(|e| format!("Failed to set HEAD: {}", e))?;
Copy link
Collaborator

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();
Copy link
Collaborator

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?

@christian-schilling christian-schilling force-pushed the @changes/master/christian.schilling.de@gmail.com/add-cli branch 4 times, most recently from 77053c0 to d860188 Compare October 12, 2025 10:33
@christian-schilling christian-schilling force-pushed the @changes/master/christian.schilling.de@gmail.com/add-cli branch 5 times, most recently from 8d10bb4 to 3f3669d Compare October 14, 2025 19:05
Change: add-cli
@christian-schilling christian-schilling force-pushed the @changes/master/christian.schilling.de@gmail.com/add-cli branch from 3f3669d to 4ebd860 Compare October 14, 2025 19:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants