55
66use std:: {
77 ffi:: OsStr ,
8+ path:: Path ,
89 process:: { Command , Stdio } ,
910 str,
1011} ;
@@ -13,55 +14,83 @@ use super::{error::DockerError, json};
1314
1415const DOCKER_PROGRAM : & str = "docker" ;
1516
16- #[ derive( Debug ) ]
17- pub struct DockerBuild {
18- pub child : std:: process:: Child ,
19- }
20-
21- impl DockerBuild {
22- pub fn file ( & mut self ) -> impl std:: io:: Write + ' _ {
23- self . child . stdin . as_mut ( ) . unwrap ( )
24- }
25-
26- pub fn wait ( mut self ) -> Result < ( ) , DockerError > {
27- self . child . wait ( ) . map_err ( DockerError :: WaitFailure ) ?;
28- Ok ( ( ) )
29- }
30- }
17+ /// Build a Docker image using a Dockerfile from an existing file.
18+ pub fn build_with_file ( tag : & str , dockerfile_path : & Path ) -> Result < ( ) , DockerError > {
19+ info ! ( @grey, "Building Docker image: {} (using Dockerfile: {})" , tag, dockerfile_path. display( ) ) ;
3120
32- /// Start a Docker build.
33- pub fn build ( tag : & str ) -> Result < DockerBuild , DockerError > {
34- let child = Command :: new ( DOCKER_PROGRAM )
21+ let mut child = Command :: new ( DOCKER_PROGRAM )
3522 . arg ( "build" )
3623 . args ( [ "--tag" , tag] )
24+ . args ( [ "--file" , dockerfile_path. to_str ( ) . unwrap ( ) ] )
3725 . arg ( "." )
38- . args ( [ "--file" , "-" ] )
39- . stdin ( Stdio :: piped ( ) )
26+ . stdout ( Stdio :: inherit ( ) )
27+ . stderr ( Stdio :: inherit ( ) )
4028 . spawn ( )
4129 . map_err ( DockerError :: CommandExecution ) ?;
42- Ok ( DockerBuild { child } )
30+
31+ let status = child. wait ( ) . map_err ( DockerError :: WaitFailure ) ?;
32+
33+ if !status. success ( ) {
34+ return Err ( DockerError :: Docker ( format ! (
35+ "Docker build failed with exit code: {}" ,
36+ status. code( ) . unwrap_or( -1 )
37+ ) ) ) ;
38+ }
39+
40+ info ! ( @grey, "Docker image built successfully: {}" , tag) ;
41+ Ok ( ( ) )
42+ }
43+
44+ /// Check if a Docker image exists on Docker Hub.
45+ pub fn image_exists_on_hub ( image_name : & str ) -> Result < bool , DockerError > {
46+ // Use docker manifest inspect to check if the image exists on the registry
47+ let output = Command :: new ( DOCKER_PROGRAM )
48+ . arg ( "manifest" )
49+ . arg ( "inspect" )
50+ . arg ( image_name)
51+ . output ( )
52+ . map_err ( DockerError :: CommandExecution ) ?;
53+
54+ // If the command succeeds, the image exists
55+ let exists = output. status . success ( ) ;
56+
57+ Ok ( exists)
4358}
4459
45- /// List local Docker images.
46- ///
47- /// We currently only use this with a repository specified.
48- pub fn images ( repository : & str ) -> Result < Vec < json:: Image > , DockerError > {
60+ /// Check if a specific Docker image exists locally.
61+ /// Returns true if the exact image:tag combination exists locally.
62+ pub fn image_exists_locally ( image_name : & str ) -> Result < bool , DockerError > {
4963 let output = Command :: new ( DOCKER_PROGRAM )
5064 . arg ( "images" )
5165 . args ( [ "--format" , "json" ] )
52- . arg ( repository )
66+ . arg ( image_name )
5367 . output ( )
5468 . map_err ( DockerError :: CommandExecution ) ?;
5569
56- if !output. status . success ( ) {
70+ let success = output. status . success ( ) ;
71+ if !success {
5772 return Err ( DockerError :: from_stderr ( output. stderr ) ) ;
5873 }
5974
60- output
75+ // Parse the JSON output to check if any images match the exact image:tag
76+ let images: Vec < json:: Image > = output
6177 . stdout
6278 . split ( |b| * b == b'\n' )
63- . map ( |slice| serde_json:: from_slice ( slice) . map_err ( Into :: into) )
64- . collect ( )
79+ . filter ( |slice| !slice. is_empty ( ) ) // Filter out empty lines
80+ . map ( |slice| serde_json:: from_slice ( slice) . map_err ( DockerError :: Json ) )
81+ . collect :: < Result < Vec < _ > , _ > > ( ) ?;
82+
83+ // Check if any image matches the exact repository:tag combination
84+ let exists = images. iter ( ) . any ( |image| {
85+ let full_name = if image. tag == "<none>" {
86+ image. repository . clone ( )
87+ } else {
88+ format ! ( "{}:{}" , image. repository, image. tag)
89+ } ;
90+ full_name == image_name
91+ } ) ;
92+
93+ Ok ( exists)
6594}
6695
6796/// Run a command in a Docker container.
0 commit comments