33//! Code to handle the setup of our pretty complex local development
44//! environment.
55
6- use crate :: util:: { execute_command, info, ok_or_error, print, psql_output, unwrap_or_exit, warn} ;
7- use std:: process:: Command ;
6+ use crate :: util:: {
7+ compare_files, error, execute_command, info, ok_or_error, print, psql_output, unwrap_or_exit,
8+ warn,
9+ } ;
10+ use std:: path:: Path ;
11+ use std:: process:: { exit, Command } ;
812
913#[ cfg( target_os ="macos" ) ]
1014static PG_INSTALL : & str ="
@@ -39,7 +43,7 @@ To install pg_stat_statements into your database:
39432. Add pg_stat_statements into your shared_preload_libraries:\n
4044\t psql -c 'ALTER SYSTEM SET shared_preload_libraries TO pgml,pg_stat_statements'
41453. Restart PostgreSQL:\n
42- \t brewservice restart postgresql@15
46+ \t brewservices restart postgresql@15
4347" ;
4448
4549#[ cfg( target_os ="linux" ) ]
@@ -55,18 +59,20 @@ To install pg_stat_statements into your database:
5559" ;
5660
5761#[ cfg( target_os ="macos" ) ]
58- static PG_PGVECTOR : & str ="Install pgvector into your PostgreSQL database:\n
59- \t git clone --branch v0.5.0 https://github.com/pgvector/pgvector &&\\
60- \t cd pgvector &&\\
62+ static PG_PGVECTOR : & str ="
63+ \t rm -rf /tmp/pgvector &&\\
64+ \t git clone --branch v0.5.0 https://github.com/pgvector/pgvector /tmp/pgvector &&\\
65+ \t cd /tmp/pgvector &&\\
6166\t echo\" trusted = true\" >> vector.control &&\\
6267\t make &&\\
6368\t make install
6469" ;
6570
6671#[ cfg( target_os ="linux" ) ]
67- static PG_PGVECTOR : & str ="Install pgvector into your PostgreSQL database:\n
68- \t git clone --branch v0.5.0 https://github.com/pgvector/pgvector &&\\
69- \t cd pgvector &&\\
72+ static PG_PGVECTOR : & str ="
73+ \t rm -rf /tmp/pgvector &&\\
74+ \t git clone --branch v0.5.0 https://github.com/pgvector/pgvector /tmp/pgvector &&\\
75+ \t cd /tmp/pgvector &&\\
7076\t echo\" trusted = true\" >> vector.control &&\\
7177\t make &&\\
7278\t sudo make install
@@ -111,7 +117,7 @@ Is PostgreSQL running and accepting connections?
111117let start =format ! (
112118"
113119To start PostgreSQL, run:\n
114- \t brewservice start postgresql@15
120+ \t brewservices start postgresql@15
115121 "
116122) ;
117123
@@ -155,18 +161,49 @@ fn dependencies() -> anyhow::Result<()> {
155161BUILD_ESSENTIAL
156162) ;
157163
158- ok_or_error ! (
159- "checking for PostgreSQL connectivity" ,
160- {
161- if let Err ( err) = psql_output( "SELECT version()" ) {
162- error!( "{}" , err) ;
163- false
164- } else{
165- true
166- }
167- } ,
168- postgres_running( )
169- ) ;
164+ #[ cfg( target_os ="macos" ) ]
165+ {
166+ print ( "checking for brew..." ) ;
167+ if execute_command ( Command :: new ( "which" ) . arg ( "brew" ) ) . is_err ( ) {
168+ error ( "missing" ) ;
169+ println ! ( "\n Brew is not installed. Install it from https://brew.sh/\n " ) ;
170+ exit ( 1 ) ;
171+ } else {
172+ info ( "ok" ) ;
173+ }
174+ }
175+
176+ #[ cfg( target_os ="linux" ) ]
177+ let postgres_service ="postgresql" ;
178+
179+ #[ cfg( target_os ="macos" ) ]
180+ let postgres_service ="postgresql@15" ;
181+
182+ print ( "checking if PostgreSQL is running..." ) ;
183+ if !check_service_running ( postgres_service) {
184+ error ( "error" ) ;
185+
186+ println ! ( "\n PostgreSQL service is not running. To start PostgreSQL, run:\n " ) ;
187+
188+ #[ cfg( target_os ="linux" ) ]
189+ println ! ( "\t sudo service postgresql start\n " ) ;
190+
191+ #[ cfg( target_os ="macos" ) ]
192+ println ! ( "\t brew services start postgresql@15\n " ) ;
193+
194+ exit ( 1 ) ;
195+ } else {
196+ info ( "ok" ) ;
197+ }
198+
199+ print ( "checking for PostgreSQL connectivity..." ) ;
200+ if let Err ( err) =psql_output ( "SELECT version()" ) {
201+ error ( "error" ) ;
202+ error ! ( "{}" , err) ;
203+ println ! ( "{}" , postgres_running( ) ) ;
204+ } else {
205+ info ( "ok" ) ;
206+ }
170207
171208ok_or_error ! (
172209"checking for pgvector PostgreSQL extension" ,
@@ -219,6 +256,7 @@ fn dependencies() -> anyhow::Result<()> {
219256let output =psql_output (
220257"SELECT datname FROM pg_database WHERE datname = 'pgml_dashboard_development'" ,
221258) ?;
259+
222260if !output. contains ( "pgml_dashboard_development" ) {
223261warn ( "missing" ) ;
224262print ( "creating pgml_dashboard_development database..." ) ;
@@ -242,6 +280,55 @@ fn dependencies() -> anyhow::Result<()> {
242280. arg( "pgml_dashboard_development" )
243281) ) ;
244282info ( "ok" ) ;
283+ } else {
284+ info ( "ok" ) ;
285+ print ( "running quick environment test..." ) ;
286+ unwrap_or_exit ! ( execute_command(
287+ Command :: new( "dropdb" )
288+ . arg( "--if-exists" )
289+ . arg( "pgml_components_environment_test" )
290+ ) ) ;
291+ unwrap_or_exit ! ( execute_command(
292+ Command :: new( "createdb" ) . arg( "pgml_components_environment_test" )
293+ ) ) ;
294+ unwrap_or_exit ! ( execute_command(
295+ Command :: new( "psql" )
296+ . arg( "-c" )
297+ . arg( "CREATE EXTENSION vector" )
298+ . arg( "pgml_components_environment_test" )
299+ ) ) ;
300+ unwrap_or_exit ! ( execute_command(
301+ Command :: new( "psql" )
302+ . arg( "-c" )
303+ . arg( "CREATE EXTENSION pgml" )
304+ . arg( "pgml_components_environment_test" )
305+ ) ) ;
306+ unwrap_or_exit ! ( execute_command(
307+ Command :: new( "dropdb" ) . arg( "pgml_components_environment_test" )
308+ ) ) ;
309+ info ( "ok" ) ;
310+ }
311+
312+ print ( "checking .env file..." ) ;
313+ let env =Path :: new ( ".env" ) ;
314+ let env_template =Path :: new ( ".env.development" ) ;
315+
316+ if !env. exists ( ) && env_template. exists ( ) {
317+ unwrap_or_exit ! ( execute_command(
318+ Command :: new( "cp" ) . arg( ".env.development" ) . arg( ".env" )
319+ ) ) ;
320+ info ( "ok" ) ;
321+ } else if env. exists ( ) && env_template. exists ( ) {
322+ let identical =unwrap_or_exit ! ( compare_files( & env, & env_template) ) ;
323+ if !identical{
324+ warn ( "different" ) ;
325+ warn ( ".env has been modified" ) ;
326+ } else {
327+ info ( "ok" ) ;
328+ }
329+ } else if !env_template. exists ( ) {
330+ warn ( "unknown" ) ;
331+ warn ( ".env.development not found, can't install or validate .env" ) ;
245332} else {
246333info ( "ok" ) ;
247334}
@@ -254,3 +341,35 @@ fn dependencies() -> anyhow::Result<()> {
254341pub fn setup ( ) {
255342unwrap_or_exit ! ( dependencies( ) )
256343}
344+
345+ pub fn install_pgvector ( ) {
346+ #[ cfg( target_os ="linux" ) ]
347+ {
348+ let check_sudo =execute_command ( Command :: new ( "sudo" ) . arg ( "ls" ) ) ;
349+ if check_sudo. is_err ( ) {
350+ println ! ( "Installing pgvector requires sudo permissions." ) ;
351+ exit ( 1 ) ;
352+ }
353+ }
354+
355+ print ( "installing pgvector PostgreSQL extension..." ) ;
356+
357+ let result =execute_command ( Command :: new ( "bash" ) . arg ( "-c" ) . arg ( PG_PGVECTOR ) ) ;
358+
359+ if let Ok ( _) = result{
360+ info ( "ok" ) ;
361+ } else if let Err ( ref err) = result{
362+ error ( "error" ) ;
363+ error ! ( "{}" , err) ;
364+ }
365+ }
366+
367+ fn check_service_running ( name : & str ) ->bool {
368+ #[ cfg( target_os ="linux" ) ]
369+ let command =format ! ( "service {} status" , name) ;
370+
371+ #[ cfg( target_os ="macos" ) ]
372+ let command =format ! ( "brew services list | grep {} | grep started" , name) ;
373+
374+ execute_command ( Command :: new ( "bash" ) . arg ( "-c" ) . arg ( & command) ) . is_ok ( )
375+ }