summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--readme.org4
-rw-r--r--src/git.rs9
-rw-r--r--tests/server_shell.rs98
3 files changed, 77 insertions, 34 deletions
diff --git a/readme.org b/readme.org
index 1153c29..4b66459 100644
--- a/readme.org
+++ b/readme.org
@@ -27,9 +27,9 @@ Pijul.
- [X] history (only within same session)
- [X] don't quit interactive shell sessions if there's an error
- [X] help command
-- [-] restrict repos to only acceptable paths
+- [X] restrict repos to only acceptable paths
- [X] clone / pull
- - [ ] push
+ - [X] push
- [ ] git init of shared repos
- [ ] listing of repos
- [ ] set repo descriptions
diff --git a/src/git.rs b/src/git.rs
index f7dbe13..b4eb3b2 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -50,11 +50,11 @@ pub fn init(repo_name: &str) -> Result<GitInitResult, ShackleError> {
}
pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleError> {
- let mut command = Command::new("git-upload-pack");
if !is_valid_personal_git_repo(&upload_pack_args.directory)? {
return Err(ShackleError::InvalidDirectory);
}
+ let mut command = Command::new("git-upload-pack");
if upload_pack_args.strict {
command.arg("strict");
}
@@ -70,7 +70,6 @@ pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleEr
if upload_pack_args.advertise_refs {
command.arg("advertise-refs");
}
-
command.arg(&upload_pack_args.directory);
command.spawn()?.wait()?;
@@ -78,12 +77,14 @@ pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleEr
}
pub fn receive_pack(receive_pack_args: &GitReceivePackArgs) -> Result<(), ShackleError> {
- let mut command = Command::new("git-receive-pack");
+ if !is_valid_personal_git_repo(&receive_pack_args.directory)? {
+ return Err(ShackleError::InvalidDirectory);
+ }
+ let mut command = Command::new("git-receive-pack");
if receive_pack_args.http_backend_info_refs {
command.arg("--http-backend-info-refs");
}
-
command.arg(&receive_pack_args.directory);
command.spawn()?.wait()?;
diff --git a/tests/server_shell.rs b/tests/server_shell.rs
index 721716b..a22b732 100644
--- a/tests/server_shell.rs
+++ b/tests/server_shell.rs
@@ -169,6 +169,36 @@ fn clone_git_repo_relative_path(c: &TestContext, repo_name: &str) -> Assert {
clone_git_repo(c, &format!("/~/git/shukkie/{}.git", repo_name))
}
+fn push_git_repo(c: &TestContext, repo_name: &str) -> Assert {
+ let repo_dir = c.workdir.as_ref().join(repo_name);
+ Command::new("git")
+ .args(["push", "origin", "main"])
+ .current_dir(&repo_dir)
+ .env("GIT_SSH_COMMAND", GIT_SSH_COMMAND)
+ .timeout(std::time::Duration::from_secs(3))
+ .assert()
+}
+
+fn commit_dummy_content(c: &TestContext, repo_name: &str) -> Result<()> {
+ let repo_dir = c.workdir.as_ref().join(repo_name);
+
+ let file_name = "yay-a-file";
+ let file_path = repo_dir.join(file_name);
+ fs::write(&file_path, "doesn't matter what this is")?;
+
+ Command::new("git")
+ .args(["add", "-A"])
+ .current_dir(&repo_dir)
+ .assert()
+ .success();
+ Command::new("git")
+ .args(["commit", "-m", "commitment"])
+ .current_dir(&repo_dir)
+ .assert()
+ .success();
+ Ok(())
+}
+
#[test]
fn git_clone_works_with_an_empty_repo() -> Result<()> {
let c = spawn_ssh_server()?;
@@ -185,51 +215,63 @@ fn git_push_works() -> Result<()> {
let repo_name = "my-new-pushable-repo";
make_new_repo(&c, repo_name)?;
clone_git_repo_relative_path(&c, repo_name).success();
+ commit_dummy_content(&c, repo_name)?;
+ push_git_repo(&c, repo_name).success();
- let repo_dir = c.workdir.as_ref().join(repo_name);
+ Ok(())
+}
- let file_name = "yay-a-file";
- let file_path = repo_dir.join(file_name);
- fs::write(&file_path, "doesn't matter what this is")?;
+#[test]
+fn git_clone_can_not_target_repo_outside_allowed_paths() -> Result<()> {
+ fn test_git_clone_unallowed_path(repo_name: &str) -> Result<()> {
+ let c = spawn_ssh_server()?;
+ clone_git_repo(&c, &format!("/~/{}.git", repo_name))
+ .failure()
+ .stderr(predicates::str::contains("Path is not accessible"));
+ Ok(())
+ }
+ test_git_clone_unallowed_path("disallowed")?;
+ test_git_clone_unallowed_path("disallowed-doesnt-exist")?;
+ Ok(())
+}
+fn init_local_git_dir(c: &TestContext, repo_name: &str) {
Command::new("git")
- .args(["add", "-A"])
- .current_dir(&repo_dir)
- .assert()
- .success();
- Command::new("git")
- .args(["commit", "-m", "commitment"])
- .current_dir(&repo_dir)
+ .args(["init", repo_name])
+ .current_dir(&c.workdir)
+ .timeout(std::time::Duration::from_secs(3))
.assert()
.success();
+ let repo_dir = c.workdir.as_ref().join(repo_name);
Command::new("git")
- .args(["push", "origin"])
+ .args([
+ "remote",
+ "add",
+ "origin",
+ &format!("ssh://shukkie@localhost:{}/~/{}.git", c.ssh_port, repo_name),
+ ])
.current_dir(&repo_dir)
- .env("GIT_SSH_COMMAND", GIT_SSH_COMMAND)
.timeout(std::time::Duration::from_secs(3))
.assert()
.success();
-
- Ok(())
}
#[test]
-fn git_clone_can_not_target_repo_outside_allowed_paths() -> Result<()> {
- let c = spawn_ssh_server()?;
- clone_git_repo(&c, "/~/disallowed.git")
- .failure()
- .stderr(predicates::str::contains("Path is not accessible"));
+fn git_push_can_not_target_repo_outside_allowed_paths() -> Result<()> {
+ fn test_push_to_unallowed_path(repo_name: &str) -> Result<()> {
+ let c = spawn_ssh_server()?;
+ init_local_git_dir(&c, &repo_name);
+ commit_dummy_content(&c, repo_name)?;
- Ok(())
-}
+ push_git_repo(&c, repo_name)
+ .failure()
+ .stderr(predicates::str::contains("Path is not accessible"));
-#[test]
-fn git_clone_can_not_target_repo_outside_allowed_paths_where_path_doesnt_exist() -> Result<()> {
- let c = spawn_ssh_server()?;
- clone_git_repo(&c, "/~/disallowed-doesnt-exist.git")
- .failure()
- .stderr(predicates::str::contains("Path is not accessible"));
+ Ok(())
+ }
+ test_push_to_unallowed_path("disallowed")?;
+ test_push_to_unallowed_path("disallowed-doesnt-exist")?;
Ok(())
}