create local repo

This commit is contained in:
2026-09-03 13:59:54 +07:00
parent 01f0540726
commit c0f06d095e
4 changed files with 155 additions and 15 deletions
+65
View File
@@ -528,6 +528,19 @@ pub fn ensure_origin(repo_path: &Path, url: &str) -> Result<()> {
Ok(())
}
/// Point `origin` at `url`, replacing an existing remote. Used after a
/// clone whose `origin` points at the cloned-from path (e.g. a working
/// copy cloned from a local mirror), to re-target it at the grasp server.
pub fn set_origin(repo_path: &Path, url: &str) -> Result<()> {
// `git remote get-url origin` exits non-zero when the remote is absent.
if git_in(repo_path, &["remote", "get-url", "origin"]).is_ok() {
git_in(repo_path, &["remote", "set-url", "origin", url])?;
} else {
git_in(repo_path, &["remote", "add", "origin", url])?;
}
Ok(())
}
/// Fetch `refspec` (e.g. `+refs/heads/*:refs/fork/<owner>/<id>/*`) into the
/// repository at `repo_path` from the first working URL in `urls`, like
/// [`clone_repo`]: `grasp://` URLs are rewritten to `https://`, the
@@ -2468,6 +2481,58 @@ mod tests {
);
}
#[test]
fn set_origin_creates_or_replaces_the_remote() {
let dir = tempfile::tempdir().expect("tempdir");
let path = dir.path().join("my-repo");
init_repository(&path, "My Repo", "").expect("init");
// No origin yet: added.
set_origin(&path, "https://gitnostr.com/npub1test/repo.git").expect("add");
assert_eq!(
origin_url(&path).expect("url").as_deref(),
Some("https://gitnostr.com/npub1test/repo.git")
);
// An existing origin is replaced, not duplicated (a clone's origin
// points at the cloned-from path; it is re-targeted at the grasp
// server).
set_origin(&path, "https://grasp.example/npub1test/repo.git").expect("replace");
assert_eq!(
origin_url(&path).expect("url").as_deref(),
Some("https://grasp.example/npub1test/repo.git")
);
}
#[test]
fn working_copy_cloned_from_the_mirror_matches_head_and_origin() {
// The mirror: a freshly initialized repository whose `origin`
// points at the grasp server, like `Backend::create_repository`
// leaves it in the GitCache.
let dir = tempfile::tempdir().expect("tempdir");
let mirror = dir.path().join("mirror");
let commit = init_repository(&mirror, "My Repo", "Does things.").expect("init");
ensure_origin(&mirror, "https://gitnostr.com/npub1test/my-repo.git").expect("origin");
// The working copy: cloned from the mirror (so it shares the
// announced history exactly), then `origin` re-pointed at the grasp
// server instead of the mirror path.
let destination = dir.path().join("folder").join("My_Repo");
std::fs::create_dir_all(destination.parent().unwrap()).expect("parent");
clone_repo(&[format!("file://{}", mirror.display())], &destination).expect("clone");
set_origin(&destination, "https://gitnostr.com/npub1test/my-repo.git").expect("set origin");
assert_eq!(
origin_url(&destination).expect("url").as_deref(),
Some("https://gitnostr.com/npub1test/my-repo.git")
);
assert_eq!(
head_commit_id(&destination).expect("head").as_deref(),
Some(commit.as_str())
);
assert!(destination.join("README.md").is_file());
}
#[test]
fn fetch_repo_refs_imports_heads_under_a_prefix() {
let dir = tempfile::tempdir().expect("tempdir");