Skip to content

Commit fb299a9

Browse files
committed
rust: modes module reorg
1 parent ab180ba commit fb299a9

File tree

5 files changed

+147
-147
lines changed

5 files changed

+147
-147
lines changed

rust/bear/src/bin/bear.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

3-
use bear::modes::combined::Combined;
4-
use bear::modes::intercept::Intercept;
5-
use bear::modes::semantic::Semantic;
6-
use bear::modes::Mode;
3+
use bear::modes::{Combined, Intercept, Mode, Semantic};
74
use bear::{args, config};
85
use std::env;
96
use std::process::ExitCode;

rust/bear/src/modes/combined.rs

Lines changed: 0 additions & 44 deletions
This file was deleted.

rust/bear/src/modes/intercept.rs

Lines changed: 15 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

3-
use super::Mode;
43
use crate::ipc::tcp::CollectorOnTcp;
54
use crate::ipc::{Collector, Envelope};
6-
use crate::output::event::write;
75
use crate::{args, config};
86
use anyhow::Context;
9-
use std::fs::OpenOptions;
10-
use std::io;
117
use std::path::{Path, PathBuf};
128
use std::process::{Command, ExitCode};
139
use std::sync::mpsc::channel;
@@ -19,56 +15,17 @@ use std::{env, thread};
1915
pub const KEY_DESTINATION: &str = "INTERCEPT_REPORTER_ADDRESS";
2016
pub const KEY_PRELOAD_PATH: &str = "LD_PRELOAD";
2117

22-
/// The intercept mode we are only capturing the build commands
23-
/// and write it into the output file.
24-
pub struct Intercept {
25-
command: args::BuildCommand,
26-
interceptor: Interceptor,
27-
}
28-
29-
impl Intercept {
30-
/// Create a new intercept mode instance.
31-
pub fn from(
32-
command: args::BuildCommand,
33-
output: args::BuildEvents,
34-
config: config::Main,
35-
) -> anyhow::Result<Self> {
36-
let file_name = output.file_name.as_str();
37-
let output_file = OpenOptions::new()
38-
.write(true)
39-
.create(true)
40-
.truncate(true)
41-
.open(file_name)
42-
.map(io::BufWriter::new)
43-
.with_context(|| format!("Failed to open file: {:?}", file_name))?;
44-
45-
let interceptor: Interceptor =
46-
Interceptor::new(config, move |envelopes| write(output_file, envelopes))?;
47-
48-
Ok(Self {
49-
command,
50-
interceptor,
51-
})
52-
}
53-
}
54-
55-
impl Mode for Intercept {
56-
/// Run the intercept mode by setting up the collector service and
57-
/// the intercept environment. The build command is executed in the
58-
/// intercept environment.
59-
///
60-
/// The exit code is based on the result of the build command.
61-
fn run(self) -> anyhow::Result<ExitCode> {
62-
self.interceptor.run_build_command(self.command)
63-
}
64-
}
65-
66-
pub(super) struct Interceptor {
18+
/// The build interceptor is responsible for capturing the build commands and
19+
/// dispatching them to the consumer. The consumer is a function that processes
20+
/// the intercepted command executions.
21+
pub(super) struct BuildInterceptor {
22+
#[allow(dead_code)]
6723
service: CollectorService,
6824
environment: InterceptEnvironment,
6925
}
7026

71-
impl Interceptor {
27+
impl BuildInterceptor {
28+
/// Create a new process execution interceptor.
7229
pub(super) fn new<F>(config: config::Main, consumer: F) -> anyhow::Result<Self>
7330
where
7431
F: FnOnce(Receiver<Envelope>) -> anyhow::Result<()>,
@@ -86,13 +43,21 @@ impl Interceptor {
8643
})
8744
}
8845

46+
/// Run the build command in the intercept environment.
8947
pub(super) fn run_build_command(self, command: args::BuildCommand) -> anyhow::Result<ExitCode> {
9048
self.environment
9149
.execute_build_command(command)
9250
.with_context(|| "Failed to execute the build command")
9351
}
9452
}
9553

54+
impl Drop for BuildInterceptor {
55+
fn drop(&mut self) {
56+
// The `CollectorService` already implements `Drop`, so we don't need to do anything here.
57+
// The `CollectorService`'s `Drop` implementation will handle the shutdown of the service.
58+
}
59+
}
60+
9661
/// The service is responsible for collecting the events from the supervised processes.
9762
///
9863
/// The service is implemented as TCP server that listens on a random port on the loopback

rust/bear/src/modes/mod.rs

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,140 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

3-
pub mod combined;
43
pub mod intercept;
54
pub mod semantic;
65

6+
use crate::modes::intercept::BuildInterceptor;
7+
use crate::modes::semantic::SemanticAnalysisPipeline;
8+
use crate::output::event::{read, write};
9+
use crate::{args, config};
10+
use anyhow::Context;
11+
use std::fs::{File, OpenOptions};
12+
use std::io;
13+
use std::io::BufReader;
714
use std::process::ExitCode;
815

916
/// The mode trait is used to run the application in different modes.
1017
pub trait Mode {
1118
fn run(self) -> anyhow::Result<ExitCode>;
1219
}
20+
21+
/// The intercept mode we are only capturing the build commands
22+
/// and write it into the output file.
23+
pub struct Intercept {
24+
command: args::BuildCommand,
25+
interceptor: BuildInterceptor,
26+
}
27+
28+
impl Intercept {
29+
/// Create a new intercept mode instance.
30+
pub fn from(
31+
command: args::BuildCommand,
32+
output: args::BuildEvents,
33+
config: config::Main,
34+
) -> anyhow::Result<Self> {
35+
let file_name = output.file_name.as_str();
36+
let output_file = OpenOptions::new()
37+
.write(true)
38+
.create(true)
39+
.truncate(true)
40+
.open(file_name)
41+
.map(io::BufWriter::new)
42+
.with_context(|| format!("Failed to open file: {:?}", file_name))?;
43+
44+
let interceptor =
45+
BuildInterceptor::new(config, move |envelopes| write(output_file, envelopes))?;
46+
47+
Ok(Self {
48+
command,
49+
interceptor,
50+
})
51+
}
52+
}
53+
54+
impl Mode for Intercept {
55+
/// Run the intercept mode by setting up the collector service and
56+
/// the intercept environment. The build command is executed in the
57+
/// intercept environment.
58+
///
59+
/// The exit code is based on the result of the build command.
60+
fn run(self) -> anyhow::Result<ExitCode> {
61+
self.interceptor.run_build_command(self.command)
62+
}
63+
}
64+
65+
/// The semantic mode we are deduct the semantic meaning of the
66+
/// executed commands from the build process.
67+
pub struct Semantic {
68+
event_file: BufReader<File>,
69+
semantic: SemanticAnalysisPipeline,
70+
}
71+
72+
impl Semantic {
73+
pub fn from(
74+
input: args::BuildEvents,
75+
output: args::BuildSemantic,
76+
config: config::Main,
77+
) -> anyhow::Result<Self> {
78+
let file_name = input.file_name.as_str();
79+
let event_file = OpenOptions::new()
80+
.read(true)
81+
.open(file_name)
82+
.map(BufReader::new)
83+
.with_context(|| format!("Failed to open file: {:?}", file_name))?;
84+
85+
let semantic = SemanticAnalysisPipeline::from(output, &config)?;
86+
87+
Ok(Self {
88+
event_file,
89+
semantic,
90+
})
91+
}
92+
}
93+
94+
impl Mode for Semantic {
95+
/// Run the semantic mode by reading the event file and analyzing the events.
96+
///
97+
/// The exit code is based on the result of the output writer.
98+
fn run(self) -> anyhow::Result<ExitCode> {
99+
self.semantic
100+
.analyze_and_write(read(self.event_file))
101+
.map(|_| ExitCode::SUCCESS)
102+
}
103+
}
104+
105+
/// The all model is combining the intercept and semantic modes.
106+
pub struct Combined {
107+
command: args::BuildCommand,
108+
interceptor: BuildInterceptor,
109+
}
110+
111+
impl Combined {
112+
/// Create a new all mode instance.
113+
pub fn from(
114+
command: args::BuildCommand,
115+
output: args::BuildSemantic,
116+
config: config::Main,
117+
) -> anyhow::Result<Self> {
118+
let semantic = SemanticAnalysisPipeline::from(output, &config)?;
119+
let interceptor = BuildInterceptor::new(config, move |envelopes| {
120+
semantic.analyze_and_write(envelopes)
121+
})?;
122+
123+
Ok(Self {
124+
command,
125+
interceptor,
126+
})
127+
}
128+
}
129+
130+
impl Mode for Combined {
131+
/// Run the all mode by setting up the collector service and the intercept environment.
132+
/// The build command is executed in the intercept environment. The collected events are
133+
/// then processed by the semantic recognition and transformation. The result is written
134+
/// to the output file.
135+
///
136+
/// The exit code is based on the result of the build command.
137+
fn run(self) -> anyhow::Result<ExitCode> {
138+
self.interceptor.run_build_command(self.command)
139+
}
140+
}

rust/bear/src/modes/semantic.rs

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,19 @@
11
// SPDX-License-Identifier: GPL-3.0-or-later
22

33
use crate::ipc::Envelope;
4-
use crate::modes::Mode;
5-
use crate::output::event::read;
64
use crate::output::{OutputWriter, OutputWriterImpl};
75
use crate::semantic::transformation::Transformation;
86
use crate::semantic::Transform;
97
use crate::{args, config, semantic};
10-
use anyhow::Context;
11-
use std::fs::{File, OpenOptions};
12-
use std::io::BufReader;
13-
use std::process::ExitCode;
14-
15-
/// The semantic mode we are deduct the semantic meaning of the
16-
/// executed commands from the build process.
17-
pub struct Semantic {
18-
event_file: BufReader<File>,
19-
semantic: SemanticFromEnvelopes,
20-
}
21-
22-
impl Semantic {
23-
pub fn from(
24-
input: args::BuildEvents,
25-
output: args::BuildSemantic,
26-
config: config::Main,
27-
) -> anyhow::Result<Self> {
28-
let file_name = input.file_name.as_str();
29-
let event_file = OpenOptions::new()
30-
.read(true)
31-
.open(file_name)
32-
.map(BufReader::new)
33-
.with_context(|| format!("Failed to open file: {:?}", file_name))?;
34-
35-
let semantic = SemanticFromEnvelopes::from(output, &config)?;
36-
37-
Ok(Self {
38-
event_file,
39-
semantic,
40-
})
41-
}
42-
}
43-
44-
impl Mode for Semantic {
45-
/// Run the semantic mode by reading the event file and analyzing the events.
46-
///
47-
/// The exit code is based on the result of the output writer.
48-
fn run(self) -> anyhow::Result<ExitCode> {
49-
self.semantic
50-
.analyze_and_write(read(self.event_file))
51-
.map(|_| ExitCode::SUCCESS)
52-
}
53-
}
548

559
/// The semantic analysis that is independent of the event source.
56-
pub struct SemanticFromEnvelopes {
10+
pub(super) struct SemanticAnalysisPipeline {
5711
interpreter: Box<dyn semantic::Interpreter>,
5812
transform: Transformation,
5913
output_writer: OutputWriterImpl,
6014
}
6115

62-
impl SemanticFromEnvelopes {
16+
impl SemanticAnalysisPipeline {
6317
/// Create a new semantic mode instance.
6418
pub(super) fn from(output: args::BuildSemantic, config: &config::Main) -> anyhow::Result<Self> {
6519
let interpreter = Self::interpreter(config)?;

0 commit comments

Comments
 (0)