Skip to content
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

Add repo cloning to check-diff crate #6187

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

benluiwj
Copy link
Contributor

@benluiwj benluiwj commented Jun 6, 2024

TLDR: Added repo cloning to check-diff. Included sample execution as screenshot.

This PR adds git functionalities to the check-diff crate. The current script has a init_submodules function. However, it seems that the repos used does not require initialising of submodules. Hence, this function was not converted to Rust.
Sample execution attached. Parameters to the program is currently not in used.
Screenshot 2024-06-06 at 9 49 18 PM
The screenshot shows the following things:

  • runs the script to clone rustfmt into a tmp directory created
  • show that tmp contains the entire rustfmt repo

Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Great first pass, though I think we can make some changes to take better advantage of the type system, and keep functions more focused on a single task. There are also a few other suggestions that I've made. Take a look and let me know if you've got any questions on the feedback.

check_diff/src/main.rs Outdated Show resolved Hide resolved
check_diff/src/main.rs Outdated Show resolved Hide resolved
check_diff/src/main.rs Outdated Show resolved Hide resolved
check_diff/src/main.rs Outdated Show resolved Hide resolved
@benluiwj benluiwj requested a review from ytmimi June 19, 2024 03:12
@benluiwj
Copy link
Contributor Author

benluiwj commented Jun 19, 2024

@ytmimi Sorry for the big PR. Things updated based on the previous review:

  • Added unit tests
  • Refactored clone_github_repo function and updated its return type
  • Replaced println in main functions with tracing instead

Some questions though:

  • tracing has the concept of a span. I was thinking where should this span be, if it exists. There are 2 places I can think of, 1) in the function itself or 2) in main.
  • The tests have a common cleanup function that removes the tmp directory created. The reason its called twice is because I am unsure of the order of execution of the tests. Is there a better way to do this?

Let me know what do you think of the updated implementation!

ps the PR is huge because I added tracing. Most changes are from the Cargo.lock file actually. The actual code is really about 100 lines (including tests)

Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Great to see that you've added some test cases to cover the functionality that you're adding. I left a few more comments about returning Results from functions instead of panicing and also I think the tempfile crate would be a nice addition to the test suite so that we don't need to roll our own temporary file and directory cleanup.

check_diff/tests/common/mod.rs Outdated Show resolved Hide resolved
check_diff/tests/git.rs Outdated Show resolved Hide resolved
check_diff/src/lib.rs Outdated Show resolved Hide resolved
check_diff/src/lib.rs Outdated Show resolved Hide resolved
@benluiwj
Copy link
Contributor Author

benluiwj commented Jun 28, 2024

Changes made from last review:

  • Added tempfile crate for unit tests
  • Polished Result of git (clone) and unix (cd) functionalities

Questions:

  1. Since errors are possible when creating the directories using tempfile, I made an assertion that is guaranteed to fail in the testcase. Not sure if there are better ways to do this. What do you think?
  2. tempfile creates directories with arbitrary names (even using prefix and suffix does not seem to mitigate it). Thus for cd_test, I have an assertion that says the current directory name is not the home directory (check_diff). This is a little odd as well since we should be testing whether we actually made it into a path that we want, not that we're not in the home directory. What do you feel should be the way we resolve this (if it needs to be resolved)?

@benluiwj benluiwj requested a review from ytmimi June 28, 2024 08:44
Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

I left some additional comments on the cd_test and clone_repo_test functions. When testing I think it's totally fine to call unwrap, and I think doing so would simplify the test cases. I also left some suggestions for more direct assertions. Overall I think the addition of the tempfile crate helped improve the tests.

#[test]
fn cd_test() {
// create directory in current directory
let dir = Builder::new().tempdir_in("");
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to use the builder here. Probably simpler to use the tempdir function and just unwrap since we're in a test case. If we fail to create the temporary directory then there's not much more we can do.

Comment on lines 21 to 27
match d.close() {
Ok(_) => {}
Err(e) => {
error!("Error from closing: {}", e);
assert_eq!(1, 2);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you explain why we need to call close here.

match dir {
Ok(d) => {
let dest_path = d.path();
let _ = change_directory_to_path(dest_path);
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably simpler to just unwrap in the test instead of silently ignoring the returned Result.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the Result here is actually ignored because we are actually changing the env variable.

Ok(d) => {
let dest_path = d.path();
let _ = change_directory_to_path(dest_path);
assert_eq!(env::current_dir().is_ok(), true);
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel like it would be a more direct test if you asserted that the current working directory is the same as the dest_path

Comment on lines 17 to 20
assert_ne!(
env::current_dir().unwrap().file_name(),
Some(OsStr::new("check_diff"))
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the code you were referring to in #6187 (comment), right? My feeling is that this isn't a necessary check and if we assert that we've correctly changed the working directory to the tempdir then I don't think this is necessary.


#[test]
fn clone_repo_test() {
let dir = Builder::new().tempdir_in("");
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar comment as before. It's probably simpler to use the tempdir function and just unwrap if we fail to create a tempdir.

Comment on lines 17 to 20
// check whether we can read this directory
assert_eq!(directory.is_err(), false);
// check that the directory is non-empty
assert_eq!(directory.iter().next().is_none(), false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we've cloned a git repo into this repository we might want to double check that a .git directory exists with the tempdir. That might be a more direct assertion. Checking that we're able to reach the directly could be useful, but my assumption would be that if we're able to write to the tempdir then we'd be able to read from it as well.

Comment on lines 21 to 28
match d.close() {
Ok(_) => {}
Err(e) => {
error!("Error from closing: {}", e);
assert_eq!(1, 2);
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Similar question as before. I'm not sure if we need to manually close the directory since it should be closed and cleaned up at the end of the test already.

@benluiwj
Copy link
Contributor Author

benluiwj commented Jul 8, 2024

Updated most of the changes that were requested as I agreed with them. The use of Builder is actually to force tempfile to create directory in the current crate directory instead of at std::env::temp_dir(). I suspect that if the testcase were to fail, the directory will not be deleted. Thus, having the temporary directory created in the same crate allows the user to manually delete the folder if that happens.

@benluiwj benluiwj requested a review from ytmimi July 8, 2024 03:24
Copy link
Contributor

@ytmimi ytmimi left a comment

Choose a reason for hiding this comment

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

Thanks for continuing to work on this. Take a look at my suggestions for simplifying the assertions.

let sample_repo = "https://github.com/rust-lang/rustfmt.git";
let dest_path = dir.path();
let result = clone_git_repo(sample_repo, dest_path);
assert_eq!(result.is_ok(), true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Simpler to use assert! here since you're testing a boolean value.

Suggested change
assert_eq!(result.is_ok(), true);
assert!(result.is_ok());

// Creates an empty directory in the current working directory
let dir = Builder::new().tempdir_in("").unwrap();
let dest_path = dir.path();
let _ = change_directory_to_path(dest_path).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

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

change_directory_to_path returns io::Result<()>. No need to bind this to anything if you're just unwrapping:

Suggested change
let _ = change_directory_to_path(dest_path).unwrap();
change_directory_to_path(dest_path).unwrap();

Comment on lines +14 to +16
let directory = fs::read_dir(dest_path);
// check that the directory is non-empty
assert_eq!(directory.iter().next().is_none(), false);
Copy link
Contributor

Choose a reason for hiding this comment

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

Probably better to do a positive assertion. Also, you can use .is_some() along with assert! to check the boolean.

Suggested change
let directory = fs::read_dir(dest_path);
// check that the directory is non-empty
assert_eq!(directory.iter().next().is_none(), false);
let directory = fs::read_dir(dest_path);
// check that the directory is non-empty
assert!(directory.iter().next().is_some());

Copy link
Contributor

Choose a reason for hiding this comment

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

This check is a little unnecessary since we're about to check that a .git folder exists, which would also prove that the directory isn't empty.

Comment on lines +17 to +24
// check whether a .git folder exists in directory
let mut is_git_present = false;
for path in directory.unwrap() {
if path.unwrap().file_name() == ".git" {
is_git_present = true;
}
}
assert_eq!(is_git_present, true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Instead of looping we can test this more directly with PathBuf::exists:

Suggested change
// check whether a .git folder exists in directory
let mut is_git_present = false;
for path in directory.unwrap() {
if path.unwrap().file_name() == ".git" {
is_git_present = true;
}
}
assert_eq!(is_git_present, true);
// check whether a .git folder exists after cloning the repo
let git_repo = dest_path.join(".git");
assert!(git_repo.exists());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants