Skip to content

Commit 2e5b938

Browse files
committed
feat: add tg::SourceMap and integrate with try_get_reference, tangram_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
1 parent 7dc7461 commit 2e5b938

File tree

29 files changed

+298
-68
lines changed

29 files changed

+298
-68
lines changed

packages/cli/src/artifact/checkout.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ impl Cli {
4242
};
4343

4444
// Get the artifact.
45-
let referent = self.get_reference(&args.reference).await?;
45+
let (referent, _) = self.get_reference(&args.reference).await?;
4646
let Either::Right(object) = referent.item else {
4747
return Err(tg::error!("expected an object"));
4848
};

packages/cli/src/cat.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl Cli {
1414
pub async fn command_cat(&self, args: Args) -> tg::Result<()> {
1515
let handle = self.handle().await?;
1616
for reference in &args.references {
17-
let referent = self.get_reference(reference).await?;
17+
let (referent, _) = self.get_reference(reference).await?;
1818
let Either::Right(object) = referent.item else {
1919
return Err(tg::error!("expected an object"));
2020
};

packages/cli/src/checksum.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub struct Args {
2121
impl Cli {
2222
pub async fn command_checksum(&self, args: Args) -> tg::Result<()> {
2323
let handle = self.handle().await?;
24-
let referent = self.get_reference(&args.reference).await?;
24+
let (referent, _) = self.get_reference(&args.reference).await?;
2525
let Either::Right(object) = referent.item else {
2626
return Err(tg::error!("expected an object"));
2727
};

packages/cli/src/get.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub struct Args {
2323
impl Cli {
2424
pub async fn command_get(&self, args: Args) -> tg::Result<()> {
2525
let handle = self.handle().await?;
26-
let referent = self.get_reference(&args.reference).await?;
26+
let (referent, _) = self.get_reference(&args.reference).await?;
2727
eprintln!("{} item {}", "info".blue().bold(), referent.item);
2828
if let Some(path) = &referent.path {
2929
let path = path.display();

packages/cli/src/lib.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crossterm::{style::Stylize as _, tty::IsTty as _};
33
use futures::FutureExt as _;
44
use num::ToPrimitive as _;
55
use std::{fmt::Write as _, path::PathBuf, sync::Mutex, time::Duration};
6-
use tangram_client::{self as tg, Client};
6+
use tangram_client::{self as tg, Client, Handle as _};
77
use tangram_either::Either;
88
use tangram_server::Server;
99
use tokio::io::AsyncWriteExt as _;
@@ -196,7 +196,7 @@ impl Cli {
196196
Ok(config) => config,
197197
Err(error) => {
198198
eprintln!("{} failed to read the config", "error".red().bold());
199-
Cli::print_error(&error, None);
199+
Cli::print_error(&error, None, None);
200200
return 1.into();
201201
},
202202
};
@@ -278,7 +278,7 @@ impl Cli {
278278
Ok(()) => 0.into(),
279279
Err(error) => {
280280
eprintln!("{} failed to run the command", "error".red().bold());
281-
Cli::print_error(&error, cli.config.as_ref());
281+
Cli::print_error(&error, cli.config.as_ref(), None);
282282
1.into()
283283
},
284284
};
@@ -904,7 +904,7 @@ impl Cli {
904904
Ok(())
905905
}
906906

907-
fn print_error(error: &tg::Error, config: Option<&Config>) {
907+
fn print_error(error: &tg::Error, config: Option<&Config>, source_map: Option<&tg::SourceMap>) {
908908
let options = config
909909
.as_ref()
910910
.and_then(|config| config.advanced.as_ref())
@@ -919,6 +919,9 @@ impl Cli {
919919
errors.reverse();
920920
}
921921
for error in errors {
922+
let error = source_map
923+
.map(|map| map.convert_error(error.clone()))
924+
.unwrap_or_else(|| error.clone());
922925
let message = error.message.as_deref().unwrap_or("an error occurred");
923926
eprintln!("{} {message}", "->".red());
924927
if let Some(location) = &error.location {
@@ -946,7 +949,10 @@ impl Cli {
946949
}
947950
}
948951

949-
fn print_diagnostic(diagnostic: &tg::Diagnostic) {
952+
fn print_diagnostic(diagnostic: &tg::Diagnostic, source_map: Option<&tg::SourceMap>) {
953+
let diagnostic = source_map
954+
.map(|map| map.convert_diagnostic(diagnostic.clone()))
955+
.unwrap_or_else(|| diagnostic.clone());
950956
let title = match diagnostic.severity {
951957
tg::diagnostic::Severity::Error => "error".red().bold(),
952958
tg::diagnostic::Severity::Warning => "warning".yellow().bold(),
@@ -1020,7 +1026,7 @@ impl Cli {
10201026
async fn get_reference(
10211027
&self,
10221028
reference: &tg::Reference,
1023-
) -> tg::Result<tg::Referent<Either<tg::Build, tg::Object>>> {
1029+
) -> tg::Result<(tg::Referent<Either<tg::Build, tg::Object>>, Option<PathBuf>)> {
10241030
let handle = self.handle().await?;
10251031
let mut item = reference.item().clone();
10261032
let mut options = reference.options().cloned();
@@ -1033,8 +1039,22 @@ impl Cli {
10331039
.map_err(|source| tg::error!(!source, "failed to get the absolute path"))?;
10341040
}
10351041
let reference = tg::Reference::with_item_and_options(&item, options.as_ref());
1036-
let referent = reference.get(&handle).await?;
1037-
Ok(referent)
1042+
let output = handle
1043+
.try_get_reference(&reference)
1044+
.await?
1045+
.ok_or_else(|| tg::error!("failed to get reference"))?;
1046+
let item = output
1047+
.referent
1048+
.item
1049+
.map_left(tg::Build::with_id)
1050+
.map_right(tg::Object::with_id);
1051+
let referent = tg::Referent {
1052+
item,
1053+
path: output.referent.path,
1054+
subpath: output.referent.subpath,
1055+
tag: output.referent.tag,
1056+
};
1057+
Ok((referent, output.lockfile))
10381058
}
10391059

10401060
/// Initialize V8.

packages/cli/src/object/export.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl Cli {
3636
.map(|remote| remote.unwrap_or_else(|| "default".to_owned()));
3737

3838
// Get the reference.
39-
let referent = self.get_reference(&reference).await?;
39+
let (referent, _) = self.get_reference(&reference).await?;
4040
let Either::Right(object) = referent.item else {
4141
return Err(tg::error!("expected an object"));
4242
};

packages/cli/src/package/check.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,22 @@ impl Cli {
2929
.map(|option| option.unwrap_or_else(|| "default".to_owned()));
3030

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

37+
// Get the source map.
38+
let source_map = if let Some(lockfile) = lockfile {
39+
let lockfile = tg::Lockfile::try_read(&lockfile)
40+
.await?
41+
.ok_or_else(|| tg::error!(%path = lockfile.display(), "failed to read lockfile"))?;
42+
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
43+
Some(source_map)
44+
} else {
45+
None
46+
};
47+
3748
// Resolve the referent.
3849
let referent = if let Some(subpath) = &referent.subpath {
3950
let directory = object
@@ -96,7 +107,7 @@ impl Cli {
96107

97108
// Print the diagnostics.
98109
for diagnostic in &output.diagnostics {
99-
Self::print_diagnostic(diagnostic);
110+
Self::print_diagnostic(diagnostic, source_map.as_ref());
100111
}
101112

102113
if !output.diagnostics.is_empty() {

packages/cli/src/package/document.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl Cli {
4343
}
4444

4545
// Get the reference.
46-
let referent = self.get_reference(&args.reference).await?;
46+
let (referent, _) = self.get_reference(&args.reference).await?;
4747
let Either::Right(object) = referent.item else {
4848
return Err(tg::error!("expected an object"));
4949
};

packages/cli/src/progress.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ impl Cli {
6161
},
6262

6363
tg::progress::Event::Diagnostic(diagnostic) => {
64-
Self::print_diagnostic(&diagnostic);
64+
Self::print_diagnostic(&diagnostic, None);
6565
},
6666

6767
tg::progress::Event::Start(indicator) | tg::progress::Event::Update(indicator) => {

packages/cli/src/pull.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl Cli {
2727
let handle = self.handle().await?;
2828

2929
// Get the reference.
30-
let referent = self.get_reference(&args.reference).await?;
30+
let (referent, _) = self.get_reference(&args.reference).await?;
3131
let item = match referent.item {
3232
Either::Left(build) => Either::Left(build),
3333
Either::Right(object) => {

packages/cli/src/push.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ impl Cli {
3434
let remote = args.remote.unwrap_or_else(|| "default".to_owned());
3535

3636
// Get the reference.
37-
let referent = self.get_reference(&args.reference).await?;
37+
let (referent, _) = self.get_reference(&args.reference).await?;
3838
let item = match referent.item {
3939
Either::Left(build) => Either::Left(build),
4040
Either::Right(object) => {

packages/cli/src/tag/put.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ impl Cli {
3030
.map(|option| option.unwrap_or_else(|| "default".to_owned()));
3131

3232
// Get the reference.
33-
let referent = self.get_reference(&args.reference).await?;
33+
let (referent, _) = self.get_reference(&args.reference).await?;
3434
let item = match referent.item {
3535
Either::Left(build) => Either::Left(build),
3636
Either::Right(object) => {

packages/cli/src/target/build.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl Cli {
178178
}
179179

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

195+
// Get the source map.
196+
let source_map = if let Some(lockfile) = lockfile {
197+
let lockfile = tg::Lockfile::try_read(&lockfile)
198+
.await?
199+
.ok_or_else(|| tg::error!(%path = lockfile.display(), "failed to read lockfile"))?;
200+
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
201+
Some(source_map)
202+
} else {
203+
None
204+
};
205+
195206
// Create the target.
196207
let target = if let tg::Object::Target(target) = object {
197208
// If the object is a target, then use it.
@@ -408,7 +419,8 @@ impl Cli {
408419
expand_on_create: true,
409420
};
410421
let item = crate::viewer::Item::Build(build);
411-
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
422+
let mut viewer =
423+
crate::viewer::Viewer::new(&handle, item, options, source_map);
412424

413425
match args.view {
414426
View::None => (),

packages/cli/src/view.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl Cli {
4141
let handle = self.handle().await?;
4242

4343
// Get the reference.
44-
let referent = self.get_reference(&args.reference).await?;
44+
let (referent, lockfile) = self.get_reference(&args.reference).await?;
4545
let item = match referent.item {
4646
Either::Left(build) => Either::Left(build),
4747
Either::Right(object) => {
@@ -57,9 +57,21 @@ impl Cli {
5757
Either::Right(object)
5858
},
5959
};
60-
let item = match item {
61-
Either::Left(build) => crate::viewer::Item::Build(build),
62-
Either::Right(object) => crate::viewer::Item::Value(object.into()),
60+
let (item, source_map) = match item {
61+
Either::Left(build) => (crate::viewer::Item::Build(build), None),
62+
Either::Right(object) => {
63+
// Get the source map.
64+
let source_map = if let Some(lockfile) = lockfile {
65+
let lockfile = tg::Lockfile::try_read(&lockfile).await?.ok_or_else(
66+
|| tg::error!(%path = lockfile.display(), "failed to read lockfile"),
67+
)?;
68+
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
69+
Some(source_map)
70+
} else {
71+
None
72+
};
73+
(crate::viewer::Item::Value(object.into()), source_map)
74+
},
6375
};
6476

6577
// Run the view.
@@ -78,7 +90,7 @@ impl Cli {
7890
condensed_builds: false,
7991
expand_on_create: matches!(kind, Kind::Inline),
8092
};
81-
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
93+
let mut viewer = crate::viewer::Viewer::new(&handle, item, options, source_map);
8294
match kind {
8395
Kind::Inline => {
8496
viewer.run_inline(stop).await?;

packages/cli/src/viewer.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,12 @@ where
145145
}
146146
}
147147

148-
pub fn new(handle: &H, item: Item, options: Options) -> Self {
148+
pub fn new(
149+
handle: &H,
150+
item: Item,
151+
options: Options,
152+
source_map: Option<tg::SourceMap>,
153+
) -> Self {
149154
let (update_sender, update_receiver) = std::sync::mpsc::channel();
150155
let data = Data::new();
151156
let tree = Tree::new(
@@ -154,6 +159,7 @@ where
154159
options,
155160
data.update_sender(),
156161
update_sender.clone(),
162+
source_map,
157163
);
158164
Self {
159165
data,

packages/cli/src/viewer/tree.rs

+7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ struct Node {
3838
log_task: Option<Task<()>>,
3939
options: Rc<Options>,
4040
parent: Option<Weak<RefCell<Self>>>,
41+
source_map: Option<Rc<tg::SourceMap>>,
4142
title: String,
4243
update_receiver: NodeUpdateReceiver,
4344
update_sender: NodeUpdateSender,
@@ -217,6 +218,7 @@ where
217218
let depth = parent.borrow().depth + 1;
218219
let (update_sender, update_receiver) = std::sync::mpsc::channel();
219220
let options = parent.borrow().options.clone();
221+
let source_map = parent.borrow().source_map.clone();
220222
let parent = Rc::downgrade(parent);
221223
let title = item.map_or(String::new(), |item| Self::item_title(item));
222224

@@ -258,6 +260,7 @@ where
258260
log_task: None,
259261
options,
260262
parent: Some(parent),
263+
source_map,
261264
title,
262265
update_receiver,
263266
update_sender,
@@ -1323,8 +1326,11 @@ where
13231326
options: Options,
13241327
data: data::UpdateSender,
13251328
viewer: super::UpdateSender<H>,
1329+
source_map: Option<tg::SourceMap>,
13261330
) -> Self {
13271331
let options = Rc::new(options);
1332+
let source_map = source_map.map(Rc::new);
1333+
13281334
let (update_sender, update_receiver) = std::sync::mpsc::channel();
13291335
let title = Self::item_title(&item);
13301336
let expand_task = if options.expand_on_create {
@@ -1367,6 +1373,7 @@ where
13671373
log_task: None,
13681374
options: options.clone(),
13691375
parent: None,
1376+
source_map,
13701377
title,
13711378
update_receiver,
13721379
update_sender,

packages/client/src/artifact/checkin.rs

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct Arg {
3434
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
3535
pub struct Output {
3636
pub artifact: tg::artifact::Id,
37+
pub lockfile: Option<PathBuf>,
3738
}
3839

3940
impl tg::Artifact {

packages/client/src/handle.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate as tg;
22
use futures::{Future, Stream};
3-
use tangram_either::Either;
43
use tokio::io::{AsyncBufRead, AsyncRead, AsyncWrite};
54

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

228226
fn list_remotes(
229227
&self,

packages/client/src/handle/either.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,7 @@ where
431431
fn try_get_reference(
432432
&self,
433433
reference: &tg::Reference,
434-
) -> impl Future<Output = tg::Result<Option<tg::Referent<Either<tg::build::Id, tg::object::Id>>>>>
435-
+ Send {
434+
) -> impl Future<Output = tg::Result<Option<tg::reference::get::Output>>> + Send {
436435
match self {
437436
Either::Left(s) => s.try_get_reference(reference).left_future(),
438437
Either::Right(s) => s.try_get_reference(reference).right_future(),

0 commit comments

Comments
 (0)