mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	Merge pull request #20280 from Kobzol/josh-sync
Switch to using josh-sync
This commit is contained in:
		
						commit
						b40fce3ccd
					
				
							
								
								
									
										11
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@ -395,15 +395,6 @@ dependencies = [
 | 
				
			|||||||
 "syn",
 | 
					 "syn",
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[package]]
 | 
					 | 
				
			||||||
name = "directories"
 | 
					 | 
				
			||||||
version = "6.0.0"
 | 
					 | 
				
			||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
					 | 
				
			||||||
checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
 | 
					 | 
				
			||||||
dependencies = [
 | 
					 | 
				
			||||||
 "dirs-sys",
 | 
					 | 
				
			||||||
]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
[[package]]
 | 
					[[package]]
 | 
				
			||||||
name = "dirs"
 | 
					name = "dirs"
 | 
				
			||||||
version = "6.0.0"
 | 
					version = "6.0.0"
 | 
				
			||||||
@ -3105,7 +3096,6 @@ name = "xtask"
 | 
				
			|||||||
version = "0.1.0"
 | 
					version = "0.1.0"
 | 
				
			||||||
dependencies = [
 | 
					dependencies = [
 | 
				
			||||||
 "anyhow",
 | 
					 "anyhow",
 | 
				
			||||||
 "directories",
 | 
					 | 
				
			||||||
 "edition",
 | 
					 "edition",
 | 
				
			||||||
 "either",
 | 
					 "either",
 | 
				
			||||||
 "flate2",
 | 
					 "flate2",
 | 
				
			||||||
@ -3113,7 +3103,6 @@ dependencies = [
 | 
				
			|||||||
 "proc-macro2",
 | 
					 "proc-macro2",
 | 
				
			||||||
 "quote",
 | 
					 "quote",
 | 
				
			||||||
 "stdx",
 | 
					 "stdx",
 | 
				
			||||||
 "time",
 | 
					 | 
				
			||||||
 "ungrammar",
 | 
					 "ungrammar",
 | 
				
			||||||
 "write-json",
 | 
					 "write-json",
 | 
				
			||||||
 "xflags",
 | 
					 "xflags",
 | 
				
			||||||
 | 
				
			|||||||
@ -252,18 +252,8 @@ Release steps:
 | 
				
			|||||||
4. Commit & push the changelog.
 | 
					4. Commit & push the changelog.
 | 
				
			||||||
5. Run `cargo xtask publish-release-notes <CHANGELOG>` -- this will convert the changelog entry in AsciiDoc to Markdown and update the body of GitHub Releases entry.
 | 
					5. Run `cargo xtask publish-release-notes <CHANGELOG>` -- this will convert the changelog entry in AsciiDoc to Markdown and update the body of GitHub Releases entry.
 | 
				
			||||||
6. Tweet.
 | 
					6. Tweet.
 | 
				
			||||||
7. Make a new branch and run `cargo xtask rustc-pull`, open a PR, and merge it.
 | 
					7. Perform a subtree [pull](#performing-a-pull).
 | 
				
			||||||
   This will pull any changes from `rust-lang/rust` into `rust-analyzer`.
 | 
					8. Perform a subtree [push](#performing-a-push).
 | 
				
			||||||
8. Switch to `master`, pull, then run `cargo xtask rustc-push --rust-path ../rust-rust-analyzer --rust-fork matklad/rust`.
 | 
					 | 
				
			||||||
   Replace `matklad/rust` with your own fork of `rust-lang/rust`.
 | 
					 | 
				
			||||||
   You can use the token to authenticate when you get prompted for a password, since `josh` will push over HTTPS, not SSH.
 | 
					 | 
				
			||||||
   This will push the `rust-analyzer` changes to your fork.
 | 
					 | 
				
			||||||
   You can then open a PR against `rust-lang/rust`.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Note: besides the `rust-rust-analyzer` clone, the Josh cache (stored under `~/.cache/rust-analyzer-josh`) will contain a bare clone of `rust-lang/rust`.
 | 
					 | 
				
			||||||
This currently takes about 3.5 GB.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This [HackMD](https://hackmd.io/7pOuxnkdQDaL1Y1FQr65xg) has details about how `josh` syncs work.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console.
 | 
					If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console.
 | 
				
			||||||
If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over.
 | 
					If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over.
 | 
				
			||||||
@ -288,3 +278,43 @@ There are two sets of people with extra permissions:
 | 
				
			|||||||
  If you don't feel like reviewing for whatever reason, someone else will pick the review up (but please speak up if you don't feel like it)!
 | 
					  If you don't feel like reviewing for whatever reason, someone else will pick the review up (but please speak up if you don't feel like it)!
 | 
				
			||||||
* The [rust-lang](https://github.com/rust-lang) team [t-rust-analyzer-contributors]([https://github.com/orgs/rust-analyzer/teams/triage](https://github.com/rust-lang/team/blob/master/teams/rust-analyzer-contributors.toml)).
 | 
					* The [rust-lang](https://github.com/rust-lang) team [t-rust-analyzer-contributors]([https://github.com/orgs/rust-analyzer/teams/triage](https://github.com/rust-lang/team/blob/master/teams/rust-analyzer-contributors.toml)).
 | 
				
			||||||
  This team has general triaging permissions allowing to label, close and re-open issues.
 | 
					  This team has general triaging permissions allowing to label, close and re-open issues.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Synchronizing subtree changes
 | 
				
			||||||
 | 
					`rust-analyzer` is a [josh](https://josh-project.github.io/josh/intro.html) subtree of the [rust-lang/rust](https://github.com/rust-lang/rust)
 | 
				
			||||||
 | 
					repository. We use the [rustc-josh-sync](https://github.com/rust-lang/josh-sync) tool to perform synchronization between these two
 | 
				
			||||||
 | 
					repositories. You can find documentation of the tool [here](https://github.com/rust-lang/josh-sync).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can install the synchronization tool using the following commands:
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					cargo install --locked --git https://github.com/rust-lang/josh-sync
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Both pulls (synchronizing changes from rust-lang/rust into rust-analyzer) and pushes (synchronizing
 | 
				
			||||||
 | 
					changes from rust-analyzer into rust-lang/rust) are performed from this repository.
 | 
				
			||||||
 | 
					changes from rust-analyzer to rust-lang/rust) are performed from this repository.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Usually we first perform a pull, wait for it to be merged, and then perform a push.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Performing a pull
 | 
				
			||||||
 | 
					1) Checkout a new branch that will be used to create a PR against rust-analyzer
 | 
				
			||||||
 | 
					2) Run the pull command
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					    rustc-josh-sync pull
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					3) Push the branch to your fork of `rust-analyzer` and create a PR
 | 
				
			||||||
 | 
					  - If you have the `gh` CLI installed, `rustc-josh-sync` can create the PR for you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Performing a push
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Wait for the previous pull to be merged.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					1) Switch to `master` and pull
 | 
				
			||||||
 | 
					2) Run the push command to create a branch named `<branch-name>` in a `rustc` fork under the `<gh-username>` account
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					    rustc-josh-sync push <branch-name> <gh-username>
 | 
				
			||||||
 | 
					    ```
 | 
				
			||||||
 | 
					   - The push will ask you to download a checkout of the `rust-lang/rust` repository.
 | 
				
			||||||
 | 
					   - If you get prompted for a password, see [this](https://github.com/rust-lang/josh-sync?tab=readme-ov-file#git-peculiarities).
 | 
				
			||||||
 | 
					3) Create a PR from `<branch-name>` into `rust-lang/rust`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					> Besides the `rust` checkout, the Josh cache (stored under `~/.cache/rustc-josh`) will contain a bare clone of `rust-lang/rust`. This currently takes several GBs.
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,6 @@ rust-version.workspace = true
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
anyhow.workspace = true
 | 
					anyhow.workspace = true
 | 
				
			||||||
directories = "6.0"
 | 
					 | 
				
			||||||
flate2 = "1.1.2"
 | 
					flate2 = "1.1.2"
 | 
				
			||||||
write-json = "0.1.4"
 | 
					write-json = "0.1.4"
 | 
				
			||||||
xshell.workspace = true
 | 
					xshell.workspace = true
 | 
				
			||||||
 | 
				
			|||||||
@ -59,20 +59,6 @@ xflags::xflags! {
 | 
				
			|||||||
            optional --dry-run
 | 
					            optional --dry-run
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cmd rustc-pull {
 | 
					 | 
				
			||||||
            /// rustc commit to pull.
 | 
					 | 
				
			||||||
            optional --commit refspec: String
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cmd rustc-push {
 | 
					 | 
				
			||||||
            /// rust local path, e.g. `../rust-rust-analyzer`.
 | 
					 | 
				
			||||||
            required --rust-path rust_path: String
 | 
					 | 
				
			||||||
            /// rust fork name, e.g.  `matklad/rust`.
 | 
					 | 
				
			||||||
            required --rust-fork rust_fork: String
 | 
					 | 
				
			||||||
            /// branch name.
 | 
					 | 
				
			||||||
            optional --branch branch: String
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        cmd dist {
 | 
					        cmd dist {
 | 
				
			||||||
            /// Use mimalloc allocator for server
 | 
					            /// Use mimalloc allocator for server
 | 
				
			||||||
            optional --mimalloc
 | 
					            optional --mimalloc
 | 
				
			||||||
@ -121,8 +107,6 @@ pub enum XtaskCmd {
 | 
				
			|||||||
    Install(Install),
 | 
					    Install(Install),
 | 
				
			||||||
    FuzzTests(FuzzTests),
 | 
					    FuzzTests(FuzzTests),
 | 
				
			||||||
    Release(Release),
 | 
					    Release(Release),
 | 
				
			||||||
    RustcPull(RustcPull),
 | 
					 | 
				
			||||||
    RustcPush(RustcPush),
 | 
					 | 
				
			||||||
    Dist(Dist),
 | 
					    Dist(Dist),
 | 
				
			||||||
    PublishReleaseNotes(PublishReleaseNotes),
 | 
					    PublishReleaseNotes(PublishReleaseNotes),
 | 
				
			||||||
    Metrics(Metrics),
 | 
					    Metrics(Metrics),
 | 
				
			||||||
@ -151,18 +135,6 @@ pub struct Release {
 | 
				
			|||||||
    pub dry_run: bool,
 | 
					    pub dry_run: bool,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub struct RustcPull {
 | 
					 | 
				
			||||||
    pub commit: Option<String>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub struct RustcPush {
 | 
					 | 
				
			||||||
    pub rust_path: String,
 | 
					 | 
				
			||||||
    pub rust_fork: String,
 | 
					 | 
				
			||||||
    pub branch: Option<String>,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					#[derive(Debug)]
 | 
				
			||||||
pub struct Dist {
 | 
					pub struct Dist {
 | 
				
			||||||
    pub mimalloc: bool,
 | 
					    pub mimalloc: bool,
 | 
				
			||||||
 | 
				
			|||||||
@ -42,8 +42,6 @@ fn main() -> anyhow::Result<()> {
 | 
				
			|||||||
        flags::XtaskCmd::Install(cmd) => cmd.run(sh),
 | 
					        flags::XtaskCmd::Install(cmd) => cmd.run(sh),
 | 
				
			||||||
        flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
 | 
					        flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
 | 
				
			||||||
        flags::XtaskCmd::Release(cmd) => cmd.run(sh),
 | 
					        flags::XtaskCmd::Release(cmd) => cmd.run(sh),
 | 
				
			||||||
        flags::XtaskCmd::RustcPull(cmd) => cmd.run(sh),
 | 
					 | 
				
			||||||
        flags::XtaskCmd::RustcPush(cmd) => cmd.run(sh),
 | 
					 | 
				
			||||||
        flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
 | 
					        flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
 | 
				
			||||||
        flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
 | 
					        flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
 | 
				
			||||||
        flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
 | 
					        flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
 | 
				
			||||||
 | 
				
			|||||||
@ -1,12 +1,5 @@
 | 
				
			|||||||
mod changelog;
 | 
					mod changelog;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::process::{Command, Stdio};
 | 
					 | 
				
			||||||
use std::thread;
 | 
					 | 
				
			||||||
use std::time::Duration;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use anyhow::{Context as _, bail};
 | 
					 | 
				
			||||||
use directories::ProjectDirs;
 | 
					 | 
				
			||||||
use stdx::JodChild;
 | 
					 | 
				
			||||||
use xshell::{Shell, cmd};
 | 
					use xshell::{Shell, cmd};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{date_iso, flags, is_release_tag, project_root};
 | 
					use crate::{date_iso, flags, is_release_tag, project_root};
 | 
				
			||||||
@ -59,171 +52,3 @@ impl flags::Release {
 | 
				
			|||||||
        Ok(())
 | 
					        Ok(())
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// git sync implementation adapted from https://github.com/rust-lang/miri/blob/62039ac/miri-script/src/commands.rs
 | 
					 | 
				
			||||||
impl flags::RustcPull {
 | 
					 | 
				
			||||||
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
 | 
					 | 
				
			||||||
        sh.change_dir(project_root());
 | 
					 | 
				
			||||||
        let commit = self.commit.map(Result::Ok).unwrap_or_else(|| {
 | 
					 | 
				
			||||||
            let rust_repo_head =
 | 
					 | 
				
			||||||
                cmd!(sh, "git ls-remote https://github.com/rust-lang/rust/ HEAD").read()?;
 | 
					 | 
				
			||||||
            rust_repo_head
 | 
					 | 
				
			||||||
                .split_whitespace()
 | 
					 | 
				
			||||||
                .next()
 | 
					 | 
				
			||||||
                .map(|front| front.trim().to_owned())
 | 
					 | 
				
			||||||
                .ok_or_else(|| anyhow::format_err!("Could not obtain Rust repo HEAD from remote."))
 | 
					 | 
				
			||||||
        })?;
 | 
					 | 
				
			||||||
        // Make sure the repo is clean.
 | 
					 | 
				
			||||||
        if !cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty() {
 | 
					 | 
				
			||||||
            bail!("working directory must be clean before running `cargo xtask pull`");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // This should not add any new root commits. So count those before and after merging.
 | 
					 | 
				
			||||||
        let num_roots = || -> anyhow::Result<u32> {
 | 
					 | 
				
			||||||
            Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count")
 | 
					 | 
				
			||||||
                .read()
 | 
					 | 
				
			||||||
                .context("failed to determine the number of root commits")?
 | 
					 | 
				
			||||||
                .parse::<u32>()?)
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        let num_roots_before = num_roots()?;
 | 
					 | 
				
			||||||
        // Make sure josh is running.
 | 
					 | 
				
			||||||
        let josh = start_josh()?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Update rust-version file. As a separate commit, since making it part of
 | 
					 | 
				
			||||||
        // the merge has confused the heck out of josh in the past.
 | 
					 | 
				
			||||||
        // We pass `--no-verify` to avoid running any git hooks that might exist,
 | 
					 | 
				
			||||||
        // in case they dirty the repository.
 | 
					 | 
				
			||||||
        sh.write_file("rust-version", format!("{commit}\n"))?;
 | 
					 | 
				
			||||||
        const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rust-lang/rust";
 | 
					 | 
				
			||||||
        cmd!(sh, "git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}")
 | 
					 | 
				
			||||||
            .run()
 | 
					 | 
				
			||||||
            .context("FAILED to commit rust-version file, something went wrong")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Fetch given rustc commit.
 | 
					 | 
				
			||||||
        cmd!(sh, "git fetch http://localhost:{JOSH_PORT}/rust-lang/rust.git@{commit}{JOSH_FILTER}.git")
 | 
					 | 
				
			||||||
            .run()
 | 
					 | 
				
			||||||
            .inspect_err(|_| {
 | 
					 | 
				
			||||||
                // Try to un-do the previous `git commit`, to leave the repo in the state we found it it.
 | 
					 | 
				
			||||||
                cmd!(sh, "git reset --hard HEAD^")
 | 
					 | 
				
			||||||
                    .run()
 | 
					 | 
				
			||||||
                    .expect("FAILED to clean up again after failed `git fetch`, sorry for that");
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Merge the fetched commit.
 | 
					 | 
				
			||||||
        const MERGE_COMMIT_MESSAGE: &str = "Merge from rust-lang/rust";
 | 
					 | 
				
			||||||
        cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}")
 | 
					 | 
				
			||||||
            .run()
 | 
					 | 
				
			||||||
            .context("FAILED to merge new commits, something went wrong")?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Check that the number of roots did not increase.
 | 
					 | 
				
			||||||
        if num_roots()? != num_roots_before {
 | 
					 | 
				
			||||||
            bail!("Josh created a new root commit. This is probably not the history you want.");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        drop(josh);
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl flags::RustcPush {
 | 
					 | 
				
			||||||
    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
 | 
					 | 
				
			||||||
        let branch = self.branch.as_deref().unwrap_or("sync-from-ra");
 | 
					 | 
				
			||||||
        let rust_path = self.rust_path;
 | 
					 | 
				
			||||||
        let rust_fork = self.rust_fork;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sh.change_dir(project_root());
 | 
					 | 
				
			||||||
        let base = sh.read_file("rust-version")?.trim().to_owned();
 | 
					 | 
				
			||||||
        // Make sure the repo is clean.
 | 
					 | 
				
			||||||
        if !cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty() {
 | 
					 | 
				
			||||||
            bail!("working directory must be clean before running `cargo xtask push`");
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // Make sure josh is running.
 | 
					 | 
				
			||||||
        let josh = start_josh()?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Find a repo we can do our preparation in.
 | 
					 | 
				
			||||||
        sh.change_dir(rust_path);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Prepare the branch. Pushing works much better if we use as base exactly
 | 
					 | 
				
			||||||
        // the commit that we pulled from last time, so we use the `rust-version`
 | 
					 | 
				
			||||||
        // file to find out which commit that would be.
 | 
					 | 
				
			||||||
        println!("Preparing {rust_fork} (base: {base})...");
 | 
					 | 
				
			||||||
        if cmd!(sh, "git fetch https://github.com/{rust_fork} {branch}")
 | 
					 | 
				
			||||||
            .ignore_stderr()
 | 
					 | 
				
			||||||
            .read()
 | 
					 | 
				
			||||||
            .is_ok()
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            bail!(
 | 
					 | 
				
			||||||
                "The branch `{branch}` seems to already exist in `https://github.com/{rust_fork}`. Please delete it and try again."
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        cmd!(sh, "git fetch https://github.com/rust-lang/rust {base}").run()?;
 | 
					 | 
				
			||||||
        cmd!(sh, "git push https://github.com/{rust_fork} {base}:refs/heads/{branch}")
 | 
					 | 
				
			||||||
            .ignore_stdout()
 | 
					 | 
				
			||||||
            .ignore_stderr() // silence the "create GitHub PR" message
 | 
					 | 
				
			||||||
            .run()?;
 | 
					 | 
				
			||||||
        println!();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Do the actual push.
 | 
					 | 
				
			||||||
        sh.change_dir(project_root());
 | 
					 | 
				
			||||||
        println!("Pushing rust-analyzer changes...");
 | 
					 | 
				
			||||||
        cmd!(
 | 
					 | 
				
			||||||
            sh,
 | 
					 | 
				
			||||||
            "git push http://localhost:{JOSH_PORT}/{rust_fork}.git{JOSH_FILTER}.git HEAD:{branch}"
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .run()?;
 | 
					 | 
				
			||||||
        println!();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Do a round-trip check to make sure the push worked as expected.
 | 
					 | 
				
			||||||
        cmd!(
 | 
					 | 
				
			||||||
            sh,
 | 
					 | 
				
			||||||
            "git fetch http://localhost:{JOSH_PORT}/{rust_fork}.git{JOSH_FILTER}.git {branch}"
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .ignore_stderr()
 | 
					 | 
				
			||||||
        .read()?;
 | 
					 | 
				
			||||||
        let head = cmd!(sh, "git rev-parse HEAD").read()?;
 | 
					 | 
				
			||||||
        let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?;
 | 
					 | 
				
			||||||
        if head != fetch_head {
 | 
					 | 
				
			||||||
            bail!(
 | 
					 | 
				
			||||||
                "Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\
 | 
					 | 
				
			||||||
                Expected {head}, got {fetch_head}."
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        println!(
 | 
					 | 
				
			||||||
            "Confirmed that the push round-trips back to rust-analyzer properly. Please create a rustc PR:"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
        // https://github.com/github-linguist/linguist/compare/master...octocat:linguist:master
 | 
					 | 
				
			||||||
        let fork_path = rust_fork.replace('/', ":");
 | 
					 | 
				
			||||||
        println!(
 | 
					 | 
				
			||||||
            "    https://github.com/rust-lang/rust/compare/{fork_path}:{branch}?quick_pull=1&title=Subtree+update+of+rust-analyzer&body=r?+@ghost"
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        drop(josh);
 | 
					 | 
				
			||||||
        Ok(())
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/// Used for rustc syncs.
 | 
					 | 
				
			||||||
const JOSH_FILTER: &str = ":rev(55d9a533b309119c8acd13061581b43ae8840823:prefix=src/tools/rust-analyzer):/src/tools/rust-analyzer";
 | 
					 | 
				
			||||||
const JOSH_PORT: &str = "42042";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
fn start_josh() -> anyhow::Result<impl Drop> {
 | 
					 | 
				
			||||||
    // Determine cache directory.
 | 
					 | 
				
			||||||
    let local_dir = {
 | 
					 | 
				
			||||||
        let user_dirs = ProjectDirs::from("org", "rust-lang", "rust-analyzer-josh").unwrap();
 | 
					 | 
				
			||||||
        user_dirs.cache_dir().to_owned()
 | 
					 | 
				
			||||||
    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // Start josh, silencing its output.
 | 
					 | 
				
			||||||
    let mut cmd = Command::new("josh-proxy");
 | 
					 | 
				
			||||||
    cmd.arg("--local").arg(local_dir);
 | 
					 | 
				
			||||||
    cmd.arg("--remote").arg("https://github.com");
 | 
					 | 
				
			||||||
    cmd.arg("--port").arg(JOSH_PORT);
 | 
					 | 
				
			||||||
    cmd.arg("--no-background");
 | 
					 | 
				
			||||||
    cmd.stdout(Stdio::null());
 | 
					 | 
				
			||||||
    cmd.stderr(Stdio::null());
 | 
					 | 
				
			||||||
    let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?;
 | 
					 | 
				
			||||||
    // Give it some time so hopefully the port is open. (100ms was not enough.)
 | 
					 | 
				
			||||||
    thread::sleep(Duration::from_millis(200));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Ok(JodChild(josh))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user