fix init
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
//! Blocking local git operations against GRASP servers.
|
||||
//!
|
||||
//! All functions may block; call them inside `cx.background_spawn`.
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
@@ -256,16 +252,15 @@ pub fn init_repository(path: &Path, name: &str, description: &str) -> Result<Str
|
||||
)?;
|
||||
|
||||
let commit = git_in(path, &["rev-parse", "HEAD"])?;
|
||||
|
||||
if commit.len() != 40 {
|
||||
bail!("unexpected initial commit id: {commit}");
|
||||
}
|
||||
|
||||
Ok(commit)
|
||||
}
|
||||
|
||||
/// Push the `main` branch of the repository at `repo_path` to a grasp
|
||||
/// server. Grasp servers speak git smart HTTP; the repository lives at
|
||||
/// `{base_url}/{owner}/{repo-id}.git` (the same path their `clone` URLs
|
||||
/// announce, per the GRASP protocol).
|
||||
/// Push the `main` branch of the repository at `repo_path` to a grasp server.
|
||||
pub fn push_main(repo_path: &Path, base_url: &str, owner: &str, repo_id: &str) -> Result<()> {
|
||||
let url = format!("{base_url}/{owner}/{repo_id}.git");
|
||||
|
||||
@@ -289,17 +284,17 @@ pub fn push_main(repo_path: &Path, base_url: &str, owner: &str, repo_id: &str) -
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Push every local branch and tag of the repository at `repo_path` to a
|
||||
/// grasp server (like `git push <url> --all --tags`), so an initialized
|
||||
/// repository's whole history is mirrored, not just `main`.
|
||||
/// Push every local branch and tag of the repository at `repo_path` to a grasp server,
|
||||
/// so an initialized repository's whole history is mirrored.
|
||||
pub fn push_all(repo_path: &Path, base_url: &str, owner: &str, repo_id: &str) -> Result<()> {
|
||||
let url = format!("{base_url}/{owner}/{repo_id}.git");
|
||||
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(repo_path)
|
||||
.args(["push", "--all", "--tags"])
|
||||
.args(["push"])
|
||||
.arg(&url)
|
||||
.args(["refs/heads/*:refs/heads/*", "refs/tags/*:refs/tags/*"])
|
||||
.env("GIT_TERMINAL_PROMPT", "0")
|
||||
.stderr(Stdio::piped())
|
||||
.output()
|
||||
@@ -311,6 +306,7 @@ pub fn push_all(repo_path: &Path, base_url: &str, owner: &str, repo_id: &str) ->
|
||||
String::from_utf8_lossy(&output.stderr).trim()
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1729,6 +1725,68 @@ mod tests {
|
||||
assert_eq!(root_commit(workdir).expect("root"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_all_mirrors_branches_and_tags() {
|
||||
// A bare "server" repository reachable via a `file://` URL, like a
|
||||
// grasp server's `{base}/{owner}/{repo-id}.git` layout.
|
||||
let server = tempfile::tempdir().unwrap();
|
||||
let server_repo = server.path().join("npub1test").join("my-repo.git");
|
||||
std::fs::create_dir_all(server_repo.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&server_repo)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let dir = dir.path();
|
||||
|
||||
// Two branches plus a tag are all mirrored.
|
||||
git_run(dir, &["checkout", "-b", "feature"]);
|
||||
std::fs::write(dir.join("b.txt"), b"two").expect("write");
|
||||
commit_all(&repo, "feature work");
|
||||
git_run(dir, &["checkout", "-"]);
|
||||
git_run(dir, &["tag", "v1.0"]);
|
||||
|
||||
let base_url = format!("file://{}", server.path().display());
|
||||
push_all(dir, &base_url, "npub1test", "my-repo").expect("push");
|
||||
|
||||
let refs = git_in(&server_repo, &["show-ref"]).expect("server refs");
|
||||
assert!(refs.contains("refs/heads/main"));
|
||||
assert!(refs.contains("refs/heads/feature"));
|
||||
assert!(refs.contains("refs/tags/v1.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn push_all_tolerates_a_missing_ref_kind() {
|
||||
// A repository with only tags (no branches) still pushes: wildcard
|
||||
// refspecs without a local match are ignored.
|
||||
let server = tempfile::tempdir().unwrap();
|
||||
let server_repo = server.path().join("npub1test").join("my-repo.git");
|
||||
std::fs::create_dir_all(server_repo.parent().unwrap()).unwrap();
|
||||
let init_status = Command::new("git")
|
||||
.args(["init", "--bare", "-q"])
|
||||
.arg(&server_repo)
|
||||
.status()
|
||||
.expect("spawn git init --bare");
|
||||
assert!(init_status.success());
|
||||
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
let dir = dir.path();
|
||||
git_run(dir, &["tag", "v1.0"]);
|
||||
git_run(dir, &["update-ref", "-d", "refs/heads/main"]);
|
||||
|
||||
let base_url = format!("file://{}", server.path().display());
|
||||
push_all(dir, &base_url, "npub1test", "my-repo").expect("push");
|
||||
|
||||
let refs = git_in(&server_repo, &["show-ref"]).expect("server refs");
|
||||
assert!(refs.contains("refs/tags/v1.0"));
|
||||
assert!(!refs.contains("refs/heads/"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn repo_ref_state_lists_branches_tags_and_head() {
|
||||
let (_dir, repo) = fixture(&[("a.txt", b"hello")]);
|
||||
|
||||
Reference in New Issue
Block a user