Unverified Commit c273bb02 authored by John DiSanti's avatar John DiSanti Committed by GitHub
Browse files

Rebase `next` off `main` before syncing (#1115)

parent f97ebf2d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -218,7 +218,7 @@ mod tests {
        let dir = TempDir::new("smithy-rs-sync_test-fs").unwrap();
        let file_path = dir.path().join(HANDWRITTEN_DOTFILE);
        // two newlines to test
        let mut handwritten_files = handwritten_files.join("\n\n");
        let handwritten_files = handwritten_files.join("\n\n");
        std::fs::write(file_path, handwritten_files).expect("failed to write");
        dir
    }
+41 −12
Original line number Diff line number Diff line
@@ -80,19 +80,11 @@ fn sync_aws_sdk_with_smithy_rs(
    branch: &str,
    max_commits_to_sync: usize,
) -> Result<()> {
    // In case these are relative paths, canonicalize them into absolute paths
    let aws_sdk = aws_sdk.canonicalize().context(here!())?;
    let smithy_rs = smithy_rs.canonicalize().context(here!())?;
    let aws_sdk = resolve_git_repo("aws-sdk-rust", aws_sdk)?;
    let smithy_rs = resolve_git_repo("smithy-rs", smithy_rs)?;

    eprintln!("aws-sdk-rust path:\t{}", aws_sdk.display());
    if !is_a_git_repository(&aws_sdk) {
        eprintln!("warning: aws-sdk-rust is not a git repository");
    }

    eprintln!("smithy-rs path:\t\t{}", smithy_rs.display());
    if !is_a_git_repository(&aws_sdk) {
        eprintln!("warning: smithy-rs is not a git repository");
    }
    // Rebase aws-sdk-rust's target branch on top of main
    rebase_on_main(&aws_sdk, branch).context(here!())?;

    // Open the repositories we'll be working with
    let smithy_rs_repo = Repository::open(&smithy_rs).context("couldn't open smithy-rs repo")?;
@@ -170,6 +162,43 @@ fn sync_aws_sdk_with_smithy_rs(
    Ok(())
}

fn resolve_git_repo(repo: &str, path: &Path) -> Result<PathBuf> {
    // In case this is a relative path, canonicalize it into an absolute path
    let full_path = path.canonicalize().context(here!())?;
    eprintln!("{} path:\t{:?}", repo, path);
    if !is_a_git_repository(path) {
        bail!("{} is not a git repository", repo);
    }
    Ok(full_path)
}

/// Rebases the given branch on top of `main`.
///
/// Running this every sync should ensure `next` will always rebase-merge cleanly
/// onto `main` when it's time for a release, and will also ensure history is common
/// between `main` and `next` after a rebase-merge occurs for release.
///
/// The reason this works is because rebasing on main will produce the exact same
/// commits as the rebase-merge pull-request will into main so long as no conflicts
/// need to be resolved. Since the sync is run regularly, this will catch conflicts
/// before syncing a commit into the target branch.
fn rebase_on_main(aws_sdk_path: &Path, branch: &str) -> Result<()> {
    let _ = run(&["git", "fetch", "origin", "main"], aws_sdk_path).context(here!())?;
    if let Err(err) = run(&["git", "rebase", "main"], aws_sdk_path) {
        bail!(
            "Failed to rebase `{0}` on top of `main`. This means there are conflicts \
            between `{0}` and `main` that need to be manually resolved. This should only \
            happen if changes were made to the same file in both `main` and `{0}` after \
            their last common ancestor commit.\
            \
            {1}",
            branch,
            err
        )
    }
    Ok(())
}

/// Starting from a given commit, walk the tree to its `HEAD` in order to build a list of commits that we'll
/// need to sync. If you don't see the commits you're expecting, make sure the repo is up to date.
/// This function doesn't include the `since_commit` in the list since that commit was synced last time