1--  This file is covered by the Internet Software Consortium (ISC) License
2--  Reference: ../License.txt
3
4package PortScan.Pilot is
5
6   --  Called when command line argument counts is known to be 2 or more.
7   --  Argument 2 should either be a path to a file or a port origin.
8   --  If it's a file, there can be no more arguments (by definition; there's
9   --  no technical issue).  If there are more than 2 arguments, arguments 2+
10   --  must all be port origins.  Returns "True" when all the port origins
11   --  (command line or inside file) are verified and arguments are correct.
12   function store_origins return Boolean;
13
14   --  Iterate through stack of individual build requests and scan each one.
15   --  If any scan fails, return False.
16   function scan_stack_of_single_ports (testmode : Boolean;
17                                        always_build : Boolean := False)
18                                        return Boolean;
19
20   --  Runs post-scan sanity check
21   --  If successful, then scans for all "ignored" ports, failing them
22   --  For each ignored port, cascade the failures (designated "skipped" ports)
23   --  Starts the build log documenting all this.
24   --  Return True if no problems are encountered.
25   function sanity_check_then_prefail (delete_first : Boolean := False;
26                                       dry_run : Boolean := False)
27                                       return Boolean;
28
29   --  Everything is fine so kick of the parallel builders.  They will
30   --  continue until everything is complete.
31   procedure perform_bulk_run (testmode : Boolean);
32
33   --  This procedure removes the single CLI listed port from the queue,
34   --  executes "perform_bulk_run" and then builds the final port, but
35   --  breaks into the jail at the specified (by ENTERAFTER env) point
36   --  The test mode is always "True" so that's not an argument.
37   procedure bulk_run_then_interact_with_final_port;
38
39   --  Return "true" if the user confirms the repository should be re/built.
40   function verify_desire_to_rebuild_repository return Boolean;
41
42   --  Return "true" if the user confirms to run "pkg upgrade" against the
43   --  local repository.
44   function verify_desire_to_install_packages return Boolean;
45
46   --  Post-build, rebuild the local repository with pkg(8)
47   --  Returns True on success
48   function rebuild_local_respository (remove_invalid_packages : Boolean) return Boolean;
49
50   --  gather every single distfile in ports tree (via distinfo) and then
51   --  search the actual package directory.  Remove non-matches without asking.
52   procedure purge_distfiles;
53
54   --  Create a pkg repo conf file (requires root permission)
55   function write_pkg_repos_configuration_file return Boolean;
56
57   --  There are no specific packages to update.  It's just a generic
58   --  "pkg upgrade" limited to local repository with "yes" confirmed.
59   procedure upgrade_system_everything (skip_installation : Boolean := False;
60                                        dry_run : Boolean := False);
61
62   --  Similar to above, but updates the packages already specified by
63   --  the "list" commands
64   procedure upgrade_system_exactly;
65
66   --  Returns True if the root users didn't execute Synth.
67   function insufficient_privileges return Boolean;
68
69   --  Returns True if a pidfile is found and it's a valid synth process
70   function already_running return Boolean;
71
72   --  Create a pidfile on major actions and remove it when complete.
73   procedure create_pidfile;
74   procedure destroy_pidfile;
75
76   --  Checks if things are mounted from aborted previous run.
77   --  The action upon "True" would be to try to clean them up (else abort)
78   function previous_run_mounts_detected return Boolean;
79
80   --  Checks if work directories are left over from aborted previous run
81   --  The action upon "True" would be to remove them completely
82   function previous_realfs_work_detected return Boolean;
83
84   --  Returns True if all the old mounts were unmounted without issue.
85   --  If not, it will emit messages so Synth can just eject directly.
86   function old_mounts_successfully_removed return Boolean;
87
88   --  Returns True if all the old SL*_(work|localbase) directories
89   --  were removed without any problems
90   function old_realfs_work_successfully_removed return Boolean;
91
92   --  libexec/synthexec is required, make sure it's installed!
93   function synthexec_missing return Boolean;
94
95   --  Scan entire ports tree
96   function fully_scan_ports_tree return Boolean;
97
98   --  List every port to be built and the final tally.  This is only done
99   --  for the status options
100   procedure display_results_of_dry_run;
101
102   --  If ENTERAFTER is defined to valid phase and there's only one port
103   --  given on the command line, then return True
104   function interact_with_single_builder return Boolean;
105
106   --  The current working directory will cause synth to fail
107   --  Known issue for when cwd is within <system root>/usr/local
108   function synth_launch_clash return Boolean;
109
110   --  Returns False if additional checks against the given system root
111   --  fail.  Currently it's only checking for FreeBSD's /boot/modules
112   function valid_system_root return Boolean;
113
114   --  returns True if CONSERVATIVE_UPGRADE option on host pkg(8) is enabled
115   function host_pkg8_conservative_upgrade_set return Boolean;
116
117   --  Return True when TERM is defined in environment (required)
118   function TERM_defined_in_environment return Boolean;
119
120   --  Pre-initialized replicant because some functionality differs depending
121   --  on the platform
122   procedure set_replicant_platform;
123
124   --  framework specific
125   --  On FreeBSD ports collection, it prebuilds pkg(8) if necessary
126   --  On Pkgsrc, it prebuilds bmake, bootstrap files and pkg(8) as necessary
127   --  Returns True unless a failure was encountered.
128   function prerequisites_available return Boolean;
129
130   --  framework specific
131   --  On FPC, it gathers all port directories (on FreeBSD, through grepping
132   --  categore makefiles and on DragonFly through reading directory entries).
133   --  Then it parallel scans the entire tree for flavors.  It saves the
134   --  sorted result at /var/cache/synth/<profile>-index.  If this file exists
135   --  and is newer than ports tree, nothing happens.
136   --  On pkgsrc, the result of gathering origins is written because flavors
137   --  are not supported.
138   function ensure_port_index return Boolean;
139
140   pilot_log : exception;
141
142private
143
144   subtype logname_field is String (1 .. 19);
145   type dim_logname  is array (count_type) of logname_field;
146   type verdiff is (newbuild, rebuild, change);
147
148   bailing : constant String := "  (Synth must exit)";
149   shutreq : constant String := "Graceful shutdown requested, exiting ...";
150   pkgng   : constant String := "ports-mgmt/pkg";
151   pidfile : constant String := "/var/run/synth.pid";
152   brkname : constant String := "ENTERAFTER";
153   dumterm : constant String := "dumb";
154   logname : constant dim_logname := ("00_last_results.log",
155                                      "01_success_list.log",
156                                      "02_failure_list.log",
157                                      "03_ignored_list.log",
158                                      "04_skipped_list.log");
159   noprocs : constant REP.slave_options := (others => False);
160   npsboot : constant REP.slave_options := (skip_cwrappers => True,
161                                            others => False);
162   duplist : portkey_crate.Map;
163
164   --  scan given file.  Everything line must be either blank (whitespace
165   --  ignored) or a valid port origin, and returns true if it is.
166   --  Internally, the ports are stacked.
167   function valid_file (path : String) return Boolean;
168
169   --  wrapper for portlist.insert that prevents duplicate key inserts
170   procedure plinsert (key : String; dummy : Natural);
171
172   --  build log operations
173   procedure start_logging (flavor : count_type);
174   procedure stop_logging (flavor : count_type);
175
176   --  generic function to return first line of file.
177   function head_n1 (filename : String) return String;
178
179   --  helper for create_pidfile
180   function Get_PID return Integer;
181   pragma Import (C, Get_PID, "getpid");
182
183   --  Query pkg(8)'s repos_dir configuration instead of assuming default
184   function get_repos_dir return String;
185
186   --  Returns octal failure of file permissions or "000" upon command failure
187   function file_permissions (full_path : String) return String;
188
189   --  Given a port ID, search for existing package in the packages directory
190   --  If the exact package exists, return " (rebuild <version>)"
191   --  If no package exists, return " (new)"
192   --  If previous package exists, return " (<oldversion> => <version>)"
193   function version_difference (id : port_id; kind : out verdiff) return String;
194
195   --  This checks for existence of both [profile]-public.key and
196   --  [profile]-private.key.  If only one exists, a non-fatal notice is
197   --  emitted saying signing configuration is incomplete (repo will not be
198   --  signed).  The permissions for the private key will be checked, and if
199   --  not 400 and owned by root, it will fail fatally.
200   --  Returns False with fatal fail, otherwises it always returns True
201   function acceptable_RSA_signing_support return Boolean;
202
203   --  The check for existence of both [profile]-signing_command and
204   --  [profile]-fingerprint.  If only one exists, a non-fatal notice is
205   --  emitted without signing the repository.  Returns True if both files
206   --  exist and aren't empty.
207   function valid_signing_command return Boolean;
208
209   --  Return the contents of the profile's signing command
210   function signing_command return String;
211
212   --  Return the contents of the profile's fingerprint
213   function profile_fingerprint return String;
214
215   --  Return True if repo is configured to be built with RSA
216   function set_synth_conf_with_RSA return Boolean;
217
218   --  converts file contents (limited to 1 line) of given file to a string
219   function one_line_file_contents (filename : String) return String;
220
221   --  Prebuilds pkg(8) in scan builder if necessary.
222   --  Returns True unless a failure was encountered.
223   function build_pkg8_as_necessary return Boolean;
224
225   --  Prebuilds bootstrap-mk files, bmake, and pkg(8)
226   --  Returns True unless a failure was encountered.
227   function build_pkgsrc_prerequisites return Boolean;
228
229   --  Returns True if index_file is older than an file or directory in the profile's
230   --  port directory
231   function index_out_of_date (index_file : String; valid : out Boolean) return Boolean;
232
233   --  Returns True if directories in index file exactly match the actual tree (meaning no
234   --  ports added or subtracted wrt index file)
235   function tree_directories_match (index_file, portsdir : String) return Boolean;
236
237end PortScan.Pilot;
238