init local repo
This commit is contained in:
@@ -289,6 +289,57 @@ 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`.
|
||||
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"])
|
||||
.arg(&url)
|
||||
.env("GIT_TERMINAL_PROMPT", "0")
|
||||
.stderr(Stdio::piped())
|
||||
.output()
|
||||
.context("failed to spawn `git push`")?;
|
||||
|
||||
if !output.status.success() {
|
||||
bail!(
|
||||
"git push to {base_url} failed: {}",
|
||||
String::from_utf8_lossy(&output.stderr).trim()
|
||||
);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The earliest unique commit of the repository at `repo_path` (a root
|
||||
/// commit, like `git rev-list --max-parents=0 HEAD`), used as the NIP-34
|
||||
/// announcement's `euc` marker. `None` for a repository without commits.
|
||||
pub fn root_commit(repo_path: &Path) -> Result<Option<String>> {
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(repo_path)
|
||||
.args(["rev-list", "--max-parents=0", "HEAD"])
|
||||
.env("GIT_TERMINAL_PROMPT", "0")
|
||||
.stderr(Stdio::piped())
|
||||
.output()
|
||||
.context("failed to spawn `git rev-list`")?;
|
||||
|
||||
// An unborn HEAD (no commits yet) makes `rev-list` fail,
|
||||
// there is no unique commit to report then.
|
||||
if !output.status.success() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(String::from_utf8_lossy(&output.stdout)
|
||||
.lines()
|
||||
.next()
|
||||
.map(str::to_owned)
|
||||
.filter(|id| id.len() == 40))
|
||||
}
|
||||
|
||||
/// Add `origin` pointing at `url` when the repository has no remote yet.
|
||||
/// No-op if `origin` already exists.
|
||||
pub fn ensure_origin(repo_path: &Path, url: &str) -> Result<()> {
|
||||
@@ -1653,6 +1704,31 @@ mod tests {
|
||||
assert_eq!(found, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn root_commit_reports_the_first_ancestor() {
|
||||
let (dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
commit_all(&repo, "initial");
|
||||
|
||||
let dir = dir.path();
|
||||
let root = root_commit(dir).expect("root").expect("commit");
|
||||
assert_eq!(root.len(), 40);
|
||||
|
||||
// The root commit does not change when history grows.
|
||||
std::fs::write(dir.join("b.txt"), b"two").expect("write");
|
||||
commit_all(&repo, "second");
|
||||
assert_eq!(
|
||||
root_commit(dir).expect("root").as_deref(),
|
||||
Some(root.as_str())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn root_commit_is_none_without_commits() {
|
||||
let (_dir, repo) = fixture(&[("a.txt", b"one")]);
|
||||
let workdir = repo.workdir().expect("workdir");
|
||||
assert_eq!(root_commit(workdir).expect("root"), None);
|
||||
}
|
||||
|
||||
#[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