Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/launch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,11 @@ impl Setup {

/// Launches vscode with the given configuration.
/// Returns the dev container that was used, if any.
pub fn launch(self, config: Option<PathBuf>) -> Result<Option<DevContainer>> {
pub fn launch(
self,
config: Option<PathBuf>,
subfolder: Option<PathBuf>,
) -> Result<Option<DevContainer>> {
let editor_name = format_editor_name(&self.behavior.command);

match self.behavior.strategy {
Expand All @@ -156,6 +160,7 @@ impl Setup {
self.dry_run,
dev_container,
&self.behavior.command,
subfolder.as_deref(),
)?;
} else {
info!("No dev container found, opening on host system with {editor_name}...");
Expand All @@ -177,6 +182,7 @@ impl Setup {
self.dry_run,
dev_container,
&self.behavior.command,
subfolder.as_deref(),
)?;
} else {
bail!(
Expand Down
56 changes: 52 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,56 @@ fn main() -> Result<()> {
match opts.command {
opts::Commands::Open { path, launch } => {
// Get workspace from args
let path = path.as_path();
let ws = Workspace::from_path(path)?;
// If a custom config is specified, derive workspace from config location
let (workspace_path, subfolder) = if let Some(ref config) = launch.config {
// Get the parent directory of the config file
let config_parent = config
.parent()
.ok_or_else(|| color_eyre::eyre::eyre!("Invalid config path"))?;

// If config is in .devcontainer folder, use its parent as workspace
let workspace_root = if config_parent
.file_name()
.map(|n| n == ".devcontainer")
.unwrap_or(false)
{
config_parent
.parent()
.ok_or_else(|| {
color_eyre::eyre::eyre!("Invalid config path structure")
})?
} else {
config_parent
};

// Handle the path argument - it might be a container path or relative path
let path_str = path.to_string_lossy();
let subfolder_path = if path_str.starts_with("/workspace/") || path_str.starts_with("/workspaces/") {
// Extract subfolder from container path
// e.g., "/workspace/vscli/tests" or "/workspaces/vscli/tests"
let parts: Vec<&str> = path_str.split('/').collect();
if parts.len() > 3 {
// Skip empty, "workspace(s)", and workspace name
Some(std::path::PathBuf::from(parts[3..].join("/")))
} else {
None
}
} else if path.is_relative() && path != std::path::Path::new(".") {
// Use relative path as-is
Some(path.to_path_buf())
} else if path.starts_with(workspace_root) {
// Calculate relative path from workspace root
path.strip_prefix(workspace_root).ok().map(|p| p.to_path_buf())
} else {
None
};

(workspace_root.to_path_buf(), subfolder_path)
} else {
(path.to_path_buf(), None)
};

let ws = Workspace::from_path(&workspace_path)?;
let ws_name = ws.name.clone();

// Open the container
Expand All @@ -69,7 +117,7 @@ fn main() -> Result<()> {
command: launch.command.unwrap_or_else(|| "code".to_string()),
};
let setup = Setup::new(ws, behavior.clone(), opts.dry_run);
let dev_container = setup.launch(launch.config)?;
let dev_container = setup.launch(launch.config, subfolder)?;

// Store the workspace in the history
tracker.history.upsert(Entry {
Expand Down Expand Up @@ -114,7 +162,7 @@ fn main() -> Result<()> {

// Open the container
let setup = Setup::new(ws, entry.behavior.clone(), opts.dry_run);
let dev_container = setup.launch(entry.config_path)?;
let dev_container = setup.launch(entry.config_path, None)?;

// Update the tracker entry
tracker.history.update(
Expand Down
15 changes: 14 additions & 1 deletion src/workspace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,27 @@ impl Workspace {
dry_run: bool,
dev_container: &DevContainer,
command: &str,
subfolder: Option<&Path>,
) -> Result<()> {
// Checking if '--folder-uri' is present in the arguments
if args.iter().any(|arg| arg == "--folder-uri") {
bail!("Specifying `--folder-uri` is not possible while using vscli.");
}

// get the folder path from the selected dev container
let container_folder: String = dev_container.workspace_path_in_container.clone();
let mut container_folder: String = dev_container.workspace_path_in_container.clone();

// Append subfolder if specified
if let Some(subfolder) = subfolder {
let subfolder_str = subfolder.to_string_lossy();
if !subfolder_str.is_empty() && subfolder_str != "." {
// Ensure proper path separator
if !container_folder.ends_with('/') {
container_folder.push('/');
}
container_folder.push_str(&subfolder_str);
}
}

let mut ws_path: String = self.path.to_string_lossy().into_owned();
let mut dc_path: String = dev_container.config_path.to_string_lossy().into_owned();
Expand Down
Loading