From 77c43cfa83da36aeefd3a915a95080827ce1a8a5 Mon Sep 17 00:00:00 2001 From: Christoph Siedentop Date: Sat, 27 Nov 2021 19:36:59 -0800 Subject: [PATCH] massive WIP working on #7. --- src/lib.rs | 13 ++++++- tests/assert_git/mod.rs | 10 ++++++ tests/common/mod.rs | 6 ++++ tests/issue_07.rs | 70 ++++++++++++++++++++++++++++++++++++++ tests/reproduce_issue07.sh | 37 ++++++++++++++++++++ tests/test.rs | 8 ----- 6 files changed, 135 insertions(+), 9 deletions(-) create mode 100644 tests/assert_git/mod.rs create mode 100644 tests/common/mod.rs create mode 100644 tests/issue_07.rs create mode 100755 tests/reproduce_issue07.sh diff --git a/src/lib.rs b/src/lib.rs index 7a55ddd..5191c8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ use eyre::{eyre, Result}; use std::process; +use std::str::from_utf8; use git2::{self, Repository, RepositoryState, ResetType}; use process::Command; @@ -57,7 +58,17 @@ pub fn cherrypick_commit_onto_new_branch( // Cherry-pick (in memory) let mut index = repo.cherrypick_commit(&fix_commit, &main_commit, 0, None)?; - let tree_oid = index.write_tree_to(&repo)?; + if index.has_conflicts() { + let conflicts = index.conflicts()?; + for conflict in conflicts { + let our_path = conflict?.our.unwrap().path; + let our = from_utf8(&our_path); + log::error!("Conflict: {:?}", our); + } + } + let tree_oid = index + .write_tree_to(&repo) + .suggestion("Could not write tree. Probably a merge conflict.")?; let tree = repo.find_tree(tree_oid)?; // The author is copied from the original commit. But the committer is set to the current user and timestamp. diff --git a/tests/assert_git/mod.rs b/tests/assert_git/mod.rs new file mode 100644 index 0000000..ae52f1b --- /dev/null +++ b/tests/assert_git/mod.rs @@ -0,0 +1,10 @@ +/// Inspired by `assert_cmd`. Asserts on a git repo. + +mod assert { + /// The point is a builder pattern on git repos. + pub struct Assert {} + + impl Repo { + // pub fn get_commits(branch: str) -> + } +} diff --git a/tests/common/mod.rs b/tests/common/mod.rs new file mode 100644 index 0000000..1f0aaea --- /dev/null +++ b/tests/common/mod.rs @@ -0,0 +1,6 @@ +use assert_cmd::Command; +use structopt::clap::crate_name; + +pub fn git_qf_binary() -> Command { + Command::cargo_bin(crate_name!()).unwrap() +} diff --git a/tests/issue_07.rs b/tests/issue_07.rs new file mode 100644 index 0000000..87847c5 --- /dev/null +++ b/tests/issue_07.rs @@ -0,0 +1,70 @@ +// https://github.com/siedentop/git-quickfix/issues/7 + +use std::fs::File; + +use assert_cmd::Command; +use eyre::Result; +use std::io::prelude::*; +use tempdir::TempDir; + +mod common; + +pub fn setup() -> String { + // let dir = TempDir::new("quickfix").unwrap(); + let path = "/tmp/gitquickfix"; + std::fs::create_dir_all(path).unwrap(); + + let out = Command::new("git") + .current_dir(path) + .arg("init") + .output() + .unwrap(); + println!("Output: {:?}, {:?}", out, path); + assert!(out.status.success(), "Failed to init git repo. {:?}", out); + + path.to_string() +} + +#[test] +fn empty_commit_on_newly_created_branch() -> Result<()> { + let dir = setup(); + let cmd = common::git_qf_binary().current_dir(dir.clone()); + + let git = |args: &[&str]| { + Command::new("git") + .current_dir(dir.clone()) + .args(args) + .output() + .unwrap() + }; + + // Create three commits, with some contents. + for (commit_message, filename, content) in [ + ("first commit", "file1.txt", b"Hello, world!\n"), + ("second commit", "file1.txt", b"Hello, world!\n"), + ("third commit", "file1.txt", b"Hello, world!\n"), + ] + .into_iter() + { + let mut file = File::create(format!("{}/{}", dir, filename))?; + file.write_all(*content)?; + + let _ = git(&["add", filename]) + .status + .success() + .then(|| ()) + .unwrap(); + let _ = git(&["commit", "-m", commit_message]) + .status + .success() + .then(|| ()) + .unwrap(); + } + + Ok(()) +} + +// fn main() { +// empty_commit_on_newly_created_branch(); +// println!("Hello"); +// } diff --git a/tests/reproduce_issue07.sh b/tests/reproduce_issue07.sh new file mode 100755 index 0000000..03cf51a --- /dev/null +++ b/tests/reproduce_issue07.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +set -ex + +export RUST_BACKTRACE=full + +REPO="https://github.com/msfjarvis/compose-lobsters" +DIR="compose-lobsters" + +if [ -d $DIR ]; then + rm -rf $DIR +fi + +git clone $REPO +cd $DIR + +git checkout develop +git reset --soft b6390003b6bb +git reset --hard + +# Do some feature development on "feature-x" +git branch feature-x b6390003b6bb +git checkout feature-x +echo "bla bla bla" >> bors.tml +git add bors.tml +git commit -m "Modify bors.tml for fun." + +# Modify the README and try to "quickfix it" +echo "This is unofficial" >> README.md +git add README.md +git commit -m "README: clarify unofficial nature" +# We just made a commit on branch 'feature-x' which should be on a different branch + +# Here we go: +git quickfix readme-updates --onto develop +cargo run --bin git-qf -- readme-updates --onto develop --force +git log --oneline -3 readme-updates diff --git a/tests/test.rs b/tests/test.rs index c5496df..fbbc423 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,11 +1,3 @@ -use assert_cmd::Command; -use structopt::clap::crate_name; -use tempdir::TempDir; - -fn git_qf_binary() -> Command { - Command::cargo_bin(crate_name!()).unwrap() -} - // Require that // 1) There shall be afterwards a branch. The commits should be going backwards: (1) the content is the same as the cherry-pick commit. (2) the next commit is the same as origin/main // 2) The original quickfix commit should not be present on the original branch. (and opposite if --keep is provided)