buildkit_llb/ops/source/
http.rs1use std::collections::HashMap;
2use std::sync::Arc;
3
4use buildkit_proto::pb::{self, op::Op, OpMetadata, SourceOp};
5
6use crate::ops::{OperationBuilder, SingleBorrowedOutput, SingleOwnedOutput};
7use crate::serialization::{Context, Node, Operation, OperationId, Result};
8use crate::utils::{OperationOutput, OutputIdx};
9
10#[derive(Default, Debug)]
11pub struct HttpSource {
12 id: OperationId,
13 url: String,
14 file_name: Option<String>,
15 description: HashMap<String, String>,
16 ignore_cache: bool,
17}
18
19impl HttpSource {
20 pub(crate) fn new<S>(url: S) -> Self
21 where
22 S: Into<String>,
23 {
24 Self {
25 id: OperationId::default(),
26 url: url.into(),
27 file_name: None,
28 description: Default::default(),
29 ignore_cache: false,
30 }
31 }
32}
33
34impl HttpSource {
35 pub fn with_file_name<S>(mut self, name: S) -> Self
36 where
37 S: Into<String>,
38 {
39 self.file_name = Some(name.into());
40 self
41 }
42}
43
44impl<'a> SingleBorrowedOutput<'a> for HttpSource {
45 fn output(&'a self) -> OperationOutput<'a> {
46 OperationOutput::borrowed(self, OutputIdx(0))
47 }
48}
49
50impl<'a> SingleOwnedOutput<'static> for Arc<HttpSource> {
51 fn output(&self) -> OperationOutput<'static> {
52 OperationOutput::owned(self.clone(), OutputIdx(0))
53 }
54}
55
56impl OperationBuilder<'static> for HttpSource {
57 fn custom_name<S>(mut self, name: S) -> Self
58 where
59 S: Into<String>,
60 {
61 self.description
62 .insert("llb.customname".into(), name.into());
63
64 self
65 }
66
67 fn ignore_cache(mut self, ignore: bool) -> Self {
68 self.ignore_cache = ignore;
69 self
70 }
71}
72
73impl Operation for HttpSource {
74 fn id(&self) -> &OperationId {
75 &self.id
76 }
77
78 fn serialize(&self, _: &mut Context) -> Result<Node> {
79 let mut attrs = HashMap::default();
80
81 if let Some(ref file_name) = self.file_name {
82 attrs.insert("http.filename".into(), file_name.into());
83 }
84
85 let head = pb::Op {
86 op: Some(Op::Source(SourceOp {
87 identifier: self.url.clone(),
88 attrs,
89 })),
90
91 ..Default::default()
92 };
93
94 let metadata = OpMetadata {
95 description: self.description.clone(),
96 ignore_cache: self.ignore_cache,
97
98 ..Default::default()
99 };
100
101 Ok(Node::new(head, metadata))
102 }
103}
104
105#[test]
106fn serialization() {
107 crate::check_op!(
108 HttpSource::new("http://any.url/with/path"),
109 |digest| { "sha256:22ec64461f39dd3b54680fc240b459248b1ced597f113b5d692abe9695860d12" },
110 |description| { vec![] },
111 |caps| { vec![] },
112 |cached_tail| { vec![] },
113 |inputs| { vec![] },
114 |op| {
115 Op::Source(SourceOp {
116 identifier: "http://any.url/with/path".into(),
117 attrs: Default::default(),
118 })
119 },
120 );
121
122 crate::check_op!(
123 HttpSource::new("http://any.url/with/path").custom_name("git custom name"),
124 |digest| { "sha256:22ec64461f39dd3b54680fc240b459248b1ced597f113b5d692abe9695860d12" },
125 |description| { vec![("llb.customname", "git custom name")] },
126 |caps| { vec![] },
127 |cached_tail| { vec![] },
128 |inputs| { vec![] },
129 |op| {
130 Op::Source(SourceOp {
131 identifier: "http://any.url/with/path".into(),
132 attrs: Default::default(),
133 })
134 },
135 );
136
137 crate::check_op!(
138 HttpSource::new("http://any.url/with/path").with_file_name("file.name"),
139 |digest| { "sha256:e1fe6584287dfa2b065ed29fcf4f77bcf86fb54781832d2f45074fa1671df692" },
140 |description| { vec![] },
141 |caps| { vec![] },
142 |cached_tail| { vec![] },
143 |inputs| { vec![] },
144 |op| {
145 Op::Source(SourceOp {
146 identifier: "http://any.url/with/path".into(),
147 attrs: vec![("http.filename".to_string(), "file.name".to_string())]
148 .into_iter()
149 .collect(),
150 })
151 },
152 );
153}