Skip to content

Commit

Permalink
feat: add tg::SourceMap and integrate with try_get_reference, tangram…
Browse files Browse the repository at this point in the history
…_cli

- created tg::reference::get::Output
- added lockfile: Option<PathBuf> to tg::reference::get::Output
- added tg::SourceMap which can be constructed from a lockfile and root object
- use tg::SourceMap to remap module referent IDs to paths/tags in diagnostics, errors, and viewer titles
  • Loading branch information
m-hilgendorf authored and nitsky committed Jan 10, 2025
1 parent 9e450cf commit 6ee50fe
Show file tree
Hide file tree
Showing 29 changed files with 298 additions and 68 deletions.
2 changes: 1 addition & 1 deletion packages/cli/src/artifact/checkout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Cli {
};

// Get the artifact.
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/cat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ impl Cli {
pub async fn command_cat(&self, args: Args) -> tg::Result<()> {
let handle = self.handle().await?;
for reference in &args.references {
let referent = self.get_reference(reference).await?;
let (referent, _) = self.get_reference(reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/checksum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pub struct Args {
impl Cli {
pub async fn command_checksum(&self, args: Args) -> tg::Result<()> {
let handle = self.handle().await?;
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct Args {
impl Cli {
pub async fn command_get(&self, args: Args) -> tg::Result<()> {
let handle = self.handle().await?;
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
eprintln!("{} item {}", "info".blue().bold(), referent.item);
if let Some(path) = &referent.path {
let path = path.display();
Expand Down
36 changes: 28 additions & 8 deletions packages/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crossterm::{style::Stylize as _, tty::IsTty as _};
use futures::FutureExt as _;
use num::ToPrimitive as _;
use std::{fmt::Write as _, path::PathBuf, sync::Mutex, time::Duration};
use tangram_client::{self as tg, Client};
use tangram_client::{self as tg, Client, Handle as _};
use tangram_either::Either;
use tangram_server::Server;
use tokio::io::AsyncWriteExt as _;
Expand Down Expand Up @@ -196,7 +196,7 @@ impl Cli {
Ok(config) => config,
Err(error) => {
eprintln!("{} failed to read the config", "error".red().bold());
Cli::print_error(&error, None);
Cli::print_error(&error, None, None);
return 1.into();
},
};
Expand Down Expand Up @@ -278,7 +278,7 @@ impl Cli {
Ok(()) => 0.into(),
Err(error) => {
eprintln!("{} failed to run the command", "error".red().bold());
Cli::print_error(&error, cli.config.as_ref());
Cli::print_error(&error, cli.config.as_ref(), None);
1.into()
},
};
Expand Down Expand Up @@ -904,7 +904,7 @@ impl Cli {
Ok(())
}

fn print_error(error: &tg::Error, config: Option<&Config>) {
fn print_error(error: &tg::Error, config: Option<&Config>, source_map: Option<&tg::SourceMap>) {
let options = config
.as_ref()
.and_then(|config| config.advanced.as_ref())
Expand All @@ -919,6 +919,9 @@ impl Cli {
errors.reverse();
}
for error in errors {
let error = source_map
.map(|map| map.convert_error(error.clone()))
.unwrap_or_else(|| error.clone());
let message = error.message.as_deref().unwrap_or("an error occurred");
eprintln!("{} {message}", "->".red());
if let Some(location) = &error.location {
Expand Down Expand Up @@ -946,7 +949,10 @@ impl Cli {
}
}

fn print_diagnostic(diagnostic: &tg::Diagnostic) {
fn print_diagnostic(diagnostic: &tg::Diagnostic, source_map: Option<&tg::SourceMap>) {
let diagnostic = source_map
.map(|map| map.convert_diagnostic(diagnostic.clone()))
.unwrap_or_else(|| diagnostic.clone());
let title = match diagnostic.severity {
tg::diagnostic::Severity::Error => "error".red().bold(),
tg::diagnostic::Severity::Warning => "warning".yellow().bold(),
Expand Down Expand Up @@ -1020,7 +1026,7 @@ impl Cli {
async fn get_reference(
&self,
reference: &tg::Reference,
) -> tg::Result<tg::Referent<Either<tg::Build, tg::Object>>> {
) -> tg::Result<(tg::Referent<Either<tg::Build, tg::Object>>, Option<PathBuf>)> {
let handle = self.handle().await?;
let mut item = reference.item().clone();
let mut options = reference.options().cloned();
Expand All @@ -1033,8 +1039,22 @@ impl Cli {
.map_err(|source| tg::error!(!source, "failed to get the absolute path"))?;
}
let reference = tg::Reference::with_item_and_options(&item, options.as_ref());
let referent = reference.get(&handle).await?;
Ok(referent)
let output = handle
.try_get_reference(&reference)
.await?
.ok_or_else(|| tg::error!("failed to get reference"))?;
let item = output
.referent
.item
.map_left(tg::Build::with_id)
.map_right(tg::Object::with_id);
let referent = tg::Referent {
item,
path: output.referent.path,
subpath: output.referent.subpath,
tag: output.referent.tag,
};
Ok((referent, output.lockfile))
}

/// Initialize V8.
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/object/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl Cli {
.map(|remote| remote.unwrap_or_else(|| "default".to_owned()));

// Get the reference.
let referent = self.get_reference(&reference).await?;
let (referent, _) = self.get_reference(&reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand Down
15 changes: 13 additions & 2 deletions packages/cli/src/package/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,22 @@ impl Cli {
.map(|option| option.unwrap_or_else(|| "default".to_owned()));

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, lockfile) = self.get_reference(&args.reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};

// Get the source map.
let source_map = if let Some(lockfile) = lockfile {
let lockfile = tg::Lockfile::try_read(&lockfile)
.await?
.ok_or_else(|| tg::error!(%path = lockfile.display(), "failed to read lockfile"))?;
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
Some(source_map)
} else {
None
};

// Resolve the referent.
let referent = if let Some(subpath) = &referent.subpath {
let directory = object
Expand Down Expand Up @@ -96,7 +107,7 @@ impl Cli {

// Print the diagnostics.
for diagnostic in &output.diagnostics {
Self::print_diagnostic(diagnostic);
Self::print_diagnostic(diagnostic, source_map.as_ref());
}

if !output.diagnostics.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/package/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Cli {
}

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ impl Cli {
},

tg::progress::Event::Diagnostic(diagnostic) => {
Self::print_diagnostic(&diagnostic);
Self::print_diagnostic(&diagnostic, None);
},

tg::progress::Event::Start(indicator) | tg::progress::Event::Update(indicator) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/pull.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ impl Cli {
let handle = self.handle().await?;

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let item = match referent.item {
Either::Left(build) => Either::Left(build),
Either::Right(object) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/push.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Cli {
let remote = args.remote.unwrap_or_else(|| "default".to_owned());

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let item = match referent.item {
Either::Left(build) => Either::Left(build),
Either::Right(object) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/src/tag/put.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Cli {
.map(|option| option.unwrap_or_else(|| "default".to_owned()));

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, _) = self.get_reference(&args.reference).await?;
let item = match referent.item {
Either::Left(build) => Either::Left(build),
Either::Right(object) => {
Expand Down
16 changes: 14 additions & 2 deletions packages/cli/src/target/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ impl Cli {
}

// Get the reference.
let referent = self.get_reference(&reference).await?;
let (referent, lockfile) = self.get_reference(&reference).await?;
let Either::Right(object) = referent.item else {
return Err(tg::error!("expected an object"));
};
Expand All @@ -192,6 +192,17 @@ impl Cli {
object
};

// Get the source map.
let source_map = if let Some(lockfile) = lockfile {
let lockfile = tg::Lockfile::try_read(&lockfile)
.await?
.ok_or_else(|| tg::error!(%path = lockfile.display(), "failed to read lockfile"))?;
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
Some(source_map)
} else {
None
};

// Create the target.
let target = if let tg::Object::Target(target) = object {
// If the object is a target, then use it.
Expand Down Expand Up @@ -408,7 +419,8 @@ impl Cli {
expand_on_create: true,
};
let item = crate::viewer::Item::Build(build);
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
let mut viewer =
crate::viewer::Viewer::new(&handle, item, options, source_map);

match args.view {
View::None => (),
Expand Down
22 changes: 17 additions & 5 deletions packages/cli/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ impl Cli {
let handle = self.handle().await?;

// Get the reference.
let referent = self.get_reference(&args.reference).await?;
let (referent, lockfile) = self.get_reference(&args.reference).await?;
let item = match referent.item {
Either::Left(build) => Either::Left(build),
Either::Right(object) => {
Expand All @@ -57,9 +57,21 @@ impl Cli {
Either::Right(object)
},
};
let item = match item {
Either::Left(build) => crate::viewer::Item::Build(build),
Either::Right(object) => crate::viewer::Item::Value(object.into()),
let (item, source_map) = match item {
Either::Left(build) => (crate::viewer::Item::Build(build), None),
Either::Right(object) => {
// Get the source map.
let source_map = if let Some(lockfile) = lockfile {
let lockfile = tg::Lockfile::try_read(&lockfile).await?.ok_or_else(
|| tg::error!(%path = lockfile.display(), "failed to read lockfile"),
)?;
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
Some(source_map)
} else {
None
};
(crate::viewer::Item::Value(object.into()), source_map)
},
};

// Run the view.
Expand All @@ -78,7 +90,7 @@ impl Cli {
condensed_builds: false,
expand_on_create: matches!(kind, Kind::Inline),
};
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
let mut viewer = crate::viewer::Viewer::new(&handle, item, options, source_map);
match kind {
Kind::Inline => {
viewer.run_inline(stop).await?;
Expand Down
8 changes: 7 additions & 1 deletion packages/cli/src/viewer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,12 @@ where
}
}

pub fn new(handle: &H, item: Item, options: Options) -> Self {
pub fn new(
handle: &H,
item: Item,
options: Options,
source_map: Option<tg::SourceMap>,
) -> Self {
let (update_sender, update_receiver) = std::sync::mpsc::channel();
let data = Data::new();
let tree = Tree::new(
Expand All @@ -154,6 +159,7 @@ where
options,
data.update_sender(),
update_sender.clone(),
source_map,
);
Self {
data,
Expand Down
7 changes: 7 additions & 0 deletions packages/cli/src/viewer/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct Node {
log_task: Option<Task<()>>,
options: Rc<Options>,
parent: Option<Weak<RefCell<Self>>>,
source_map: Option<Rc<tg::SourceMap>>,
title: String,
update_receiver: NodeUpdateReceiver,
update_sender: NodeUpdateSender,
Expand Down Expand Up @@ -217,6 +218,7 @@ where
let depth = parent.borrow().depth + 1;
let (update_sender, update_receiver) = std::sync::mpsc::channel();
let options = parent.borrow().options.clone();
let source_map = parent.borrow().source_map.clone();
let parent = Rc::downgrade(parent);
let title = item.map_or(String::new(), |item| Self::item_title(item));

Expand Down Expand Up @@ -258,6 +260,7 @@ where
log_task: None,
options,
parent: Some(parent),
source_map,
title,
update_receiver,
update_sender,
Expand Down Expand Up @@ -1323,8 +1326,11 @@ where
options: Options,
data: data::UpdateSender,
viewer: super::UpdateSender<H>,
source_map: Option<tg::SourceMap>,
) -> Self {
let options = Rc::new(options);
let source_map = source_map.map(Rc::new);

let (update_sender, update_receiver) = std::sync::mpsc::channel();
let title = Self::item_title(&item);
let expand_task = if options.expand_on_create {
Expand Down Expand Up @@ -1367,6 +1373,7 @@ where
log_task: None,
options: options.clone(),
parent: None,
source_map,
title,
update_receiver,
update_sender,
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/artifact/checkin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub struct Arg {
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct Output {
pub artifact: tg::artifact::Id,
pub lockfile: Option<PathBuf>,
}

impl tg::Artifact {
Expand Down
4 changes: 1 addition & 3 deletions packages/client/src/handle.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use crate as tg;
use futures::{Future, Stream};
use tangram_either::Either;
use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite};

mod either;
Expand Down Expand Up @@ -222,8 +221,7 @@ pub trait Handle: Clone + Unpin + Send + Sync + 'static {
fn try_get_reference(
&self,
reference: &tg::Reference,
) -> impl Future<Output = tg::Result<Option<tg::Referent<Either<tg::build::Id, tg::object::Id>>>>>
+ Send;
) -> impl Future<Output = tg::Result<Option<tg::reference::get::Output>>> + Send;

fn list_remotes(
&self,
Expand Down
3 changes: 1 addition & 2 deletions packages/client/src/handle/either.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,7 @@ where
fn try_get_reference(
&self,
reference: &tg::Reference,
) -> impl Future<Output = tg::Result<Option<tg::Referent<Either<tg::build::Id, tg::object::Id>>>>>
+ Send {
) -> impl Future<Output = tg::Result<Option<tg::reference::get::Output>>> + Send {
match self {
Either::Left(s) => s.try_get_reference(reference).left_future(),
Either::Right(s) => s.try_get_reference(reference).right_future(),
Expand Down
Loading

0 comments on commit 6ee50fe

Please sign in to comment.