Skip to content

Commit db9a911

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 cf0b3ee commit db9a911

35 files changed

+350
-78
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/config.rs

+4
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,10 @@ pub struct Build {
202202
#[serde(default, skip_serializing_if = "Option::is_none")]
203203
pub max_depth: Option<u64>,
204204

205+
/// Configure if path and tag are set for builds.
206+
#[serde(default, skip_serializing_if = "Option::is_none")]
207+
pub set_path_and_tag: Option<bool>,
208+
205209
/// The remotes to build for.
206210
#[serde(default, skip_serializing_if = "Option::is_none")]
207211
pub remotes: Option<Vec<String>>,

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 _;
@@ -190,7 +190,7 @@ impl Cli {
190190
Ok(config) => config,
191191
Err(error) => {
192192
eprintln!("{} failed to read the config", "error".red().bold());
193-
Cli::print_error(&error, None);
193+
Cli::print_error(&error, None, None);
194194
return 1.into();
195195
},
196196
};
@@ -272,7 +272,7 @@ impl Cli {
272272
Ok(()) => 0.into(),
273273
Err(error) => {
274274
eprintln!("{} failed to run the command", "error".red().bold());
275-
Cli::print_error(&error, cli.config.as_ref());
275+
Cli::print_error(&error, cli.config.as_ref(), None);
276276
1.into()
277277
},
278278
};
@@ -896,7 +896,7 @@ impl Cli {
896896
Ok(())
897897
}
898898

899-
fn print_error(error: &tg::Error, config: Option<&Config>) {
899+
fn print_error(error: &tg::Error, config: Option<&Config>, source_map: Option<&tg::SourceMap>) {
900900
let options = config
901901
.as_ref()
902902
.and_then(|config| config.advanced.as_ref())
@@ -911,6 +911,9 @@ impl Cli {
911911
errors.reverse();
912912
}
913913
for error in errors {
914+
let error = source_map
915+
.map(|map| map.convert_error(error.clone()))
916+
.unwrap_or_else(|| error.clone());
914917
let message = error.message.as_deref().unwrap_or("an error occurred");
915918
eprintln!("{} {message}", "->".red());
916919
if let Some(location) = &error.location {
@@ -938,7 +941,10 @@ impl Cli {
938941
}
939942
}
940943

941-
fn print_diagnostic(diagnostic: &tg::Diagnostic) {
944+
fn print_diagnostic(diagnostic: &tg::Diagnostic, source_map: Option<&tg::SourceMap>) {
945+
let diagnostic = source_map
946+
.map(|map| map.convert_diagnostic(diagnostic.clone()))
947+
.unwrap_or_else(|| diagnostic.clone());
942948
let title = match diagnostic.severity {
943949
tg::diagnostic::Severity::Error => "error".red().bold(),
944950
tg::diagnostic::Severity::Warning => "warning".yellow().bold(),
@@ -1012,7 +1018,7 @@ impl Cli {
10121018
async fn get_reference(
10131019
&self,
10141020
reference: &tg::Reference,
1015-
) -> tg::Result<tg::Referent<Either<tg::Build, tg::Object>>> {
1021+
) -> tg::Result<(tg::Referent<Either<tg::Build, tg::Object>>, Option<PathBuf>)> {
10161022
let handle = self.handle().await?;
10171023
let mut item = reference.item().clone();
10181024
let mut options = reference.options().cloned();
@@ -1025,8 +1031,22 @@ impl Cli {
10251031
.map_err(|source| tg::error!(!source, "failed to get the absolute path"))?;
10261032
}
10271033
let reference = tg::Reference::with_item_and_options(&item, options.as_ref());
1028-
let referent = reference.get(&handle).await?;
1029-
Ok(referent)
1034+
let output = handle
1035+
.try_get_reference(&reference)
1036+
.await?
1037+
.ok_or_else(|| tg::error!("failed to get reference"))?;
1038+
let item = output
1039+
.referent
1040+
.item
1041+
.map_left(tg::Build::with_id)
1042+
.map_right(tg::Object::with_id);
1043+
let referent = tg::Referent {
1044+
item,
1045+
path: output.referent.path,
1046+
subpath: output.referent.subpath,
1047+
tag: output.referent.tag,
1048+
};
1049+
Ok((referent, output.lockfile))
10301050
}
10311051

10321052
/// Initialize V8.

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
@@ -72,7 +72,7 @@ impl Cli {
7272
},
7373

7474
tg::progress::Event::Diagnostic(diagnostic) => {
75-
Self::print_diagnostic(&diagnostic);
75+
Self::print_diagnostic(&diagnostic, None);
7676
},
7777

7878
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

+15-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, lock) = 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), Some(lockfile))
202+
} else {
203+
(None, 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.
@@ -341,6 +352,7 @@ impl Cli {
341352
let id = target.id(&handle).await?;
342353
let arg = tg::target::build::Arg {
343354
create: args.create,
355+
lock,
344356
parent: None,
345357
remote: remote.clone(),
346358
retry,
@@ -408,7 +420,8 @@ impl Cli {
408420
expand_on_create: true,
409421
};
410422
let item = crate::viewer::Item::Build(build);
411-
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
423+
let mut viewer =
424+
crate::viewer::Viewer::new(&handle, item, options, source_map);
412425

413426
match args.view {
414427
View::None => (),

packages/cli/src/view.rs

+34-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::Cli;
2-
use tangram_client as tg;
2+
use tangram_client::{self as tg, handle::Ext as _};
33
use tangram_either::Either;
44
use tangram_futures::task::Task;
55

@@ -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,37 @@ 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) => {
62+
let source_map = if let Some(lockfile) = handle.get_build(build.id()).await?.lock {
63+
// Only attempt to load the target if the lock is set.
64+
if let Some(executable) =
65+
&*build.target(&handle).await?.executable(&handle).await?
66+
{
67+
let object = executable.object()[0].clone();
68+
let source_map = tg::SourceMap::new(&handle, &lockfile, object).await?;
69+
Some(source_map)
70+
} else {
71+
None
72+
}
73+
} else {
74+
None
75+
};
76+
(crate::viewer::Item::Build(build), source_map)
77+
},
78+
Either::Right(object) => {
79+
// Get the source map.
80+
let source_map = if let Some(lockfile) = lockfile {
81+
let lockfile = tg::Lockfile::try_read(&lockfile).await?.ok_or_else(
82+
|| tg::error!(%path = lockfile.display(), "failed to read lockfile"),
83+
)?;
84+
let source_map = tg::SourceMap::new(&handle, &lockfile, object.clone()).await?;
85+
Some(source_map)
86+
} else {
87+
None
88+
};
89+
(crate::viewer::Item::Value(object.into()), source_map)
90+
},
6391
};
6492

6593
// Run the view.
@@ -78,7 +106,7 @@ impl Cli {
78106
condensed_builds: false,
79107
expand_on_create: matches!(kind, Kind::Inline),
80108
};
81-
let mut viewer = crate::viewer::Viewer::new(&handle, item, options);
109+
let mut viewer = crate::viewer::Viewer::new(&handle, item, options, source_map);
82110
match kind {
83111
Kind::Inline => {
84112
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,

0 commit comments

Comments
 (0)