diff --git a/src/bin/devbox/commands/build.rs b/src/bin/devbox/commands/build.rs index f73b51e..9c08475 100644 --- a/src/bin/devbox/commands/build.rs +++ b/src/bin/devbox/commands/build.rs @@ -12,7 +12,7 @@ pub fn exec(args: &ArgMatches) -> CliResult { let mut project = args.project()?; if let Some(name) = args.value_of("SERVICE") { - let mut service = project.find_service(name)?; + let service = project.find_service(name)?; let _ = service.clone_repo(); service.build() } else { diff --git a/src/bin/devbox/commands/mod.rs b/src/bin/devbox/commands/mod.rs index e3b58ea..f30f6ef 100644 --- a/src/bin/devbox/commands/mod.rs +++ b/src/bin/devbox/commands/mod.rs @@ -8,6 +8,7 @@ pub fn builtins() -> Vec { logs::cli(), new::cli(), ps::cli(), + renew::cli(), start::cli(), stop::cli(), tasks::cli(), @@ -23,6 +24,7 @@ pub fn builtin_exec(cmd: &str) -> Option CliResult> { "logs" => logs::exec, "new" => new::exec, "ps" => ps::exec, + "renew" => renew::exec, "start" => start::exec, "stop" => stop::exec, "tasks" => tasks::exec, @@ -38,6 +40,7 @@ pub mod doctor; pub mod logs; pub mod new; pub mod ps; +pub mod renew; pub mod start; pub mod stop; pub mod tasks; diff --git a/src/bin/devbox/commands/renew.rs b/src/bin/devbox/commands/renew.rs new file mode 100644 index 0000000..18d0d2c --- /dev/null +++ b/src/bin/devbox/commands/renew.rs @@ -0,0 +1,22 @@ +use prelude::*; + +pub fn cli() -> App { + subcommand("renew") + .about("Re-generates an existing devbox project template from a git repository") + .arg(project()) + .arg( + Arg::with_name("git") + .long("git") + .takes_value(true) + .required(true) + .help("A URL to a git repository containing configuration for this project"), + ) +} + +pub fn exec(args: &ArgMatches) -> CliResult { + let name = args.value_of("PROJECT") + .ok_or_else(|| format_err!("Missing project name"))?; + let repo = args.value_of("git") + .ok_or_else(|| format_err!("Missing git repository URL!"))?; + Project::update_from_git(name, repo) +} diff --git a/src/project.rs b/src/project.rs index 3bf6b4c..179c9c2 100644 --- a/src/project.rs +++ b/src/project.rs @@ -189,6 +189,31 @@ impl Project { Ok(()) } + pub fn update_from_git(name: &str, git: &str) -> Result<()> { + + let dir = TempDir::new("devbox")?; + + let _ = Command::new("git") + .arg("clone") + .arg(git) + .arg(&dir.path()) + .spawn()? + .wait(); + + let toml_path = &dir.path().join("config.toml"); + let yaml_path = &dir.path().join("docker-compose.yml"); + let toml_contents = read_file(&toml_path)?; + let yaml_contents = read_file(&yaml_path)?; + + ensure_directory_exists(&devbox_dir(name)?); + create_or_overwrite_file(&toml_config_path(name)?, &toml_contents)?; + create_or_overwrite_file(&yaml_config_path(name)?, &yaml_contents)?; + + dir.close()?; + + Ok(()) + } + pub fn find_service(&mut self, name: &str) -> Result<&mut Service> { let service = self.services .iter_mut() @@ -255,3 +280,17 @@ fn create_file_if_not_exists(path: &Path, content: &str) -> Result<()> { Ok(()) } + +fn create_or_overwrite_file(path: &Path, content: &str) -> Result<()> { + if path.exists() { + let mut file = OpenOptions::new().write(true).truncate(true).open(path)?; + + println!("Overwriting file {:?}", &path); + + file.write_all(content.as_bytes())?; + } else { + create_file_if_not_exists(&path, &content)?; + } + + Ok(()) +}