OSDN Git Service

Made portsreinstall-upgrade available even pkg(8) is not installed at first.
[portsreinstall/current.git] / lib / upgrade / libcommand_do.sh
1 #!/bin/sh -e
2 # ==============================================================================
3 # portsreinstall library script
4 # Overlay onto lib/libcommand_do.sh for portsreinstall-upgrade
5 # - "do" command operation -
6 # Copyright (C) 2018 Mamoru Sakaue, MwGhennndo, All Rights Reserved.
7 # This software is distributed under the 2-Clause BSD License.
8 # ==============================================================================
9
10 # ============= Set up the manifest =============
11 command_do_setup_manifest ()
12 {
13         local PROGRAM_DEPENDS
14         PROGRAM_DEPENDS=
15         _program_exec_and_record_completion__operation ()
16         {
17                 message_section_title "Setting up the list of ports to reinstall"
18                 pkg_get_pkgs_timestamps > ${DBDIR}/initial_pkgs_snapshot.csv
19                 message_echo
20         }
21         program_exec_and_record_completion SETUP_MANIFEST
22 }
23
24 # ============= Check of package paths =============
25 command_do_chk_pkg_paths ()
26 {
27         local PROGRAM_DEPENDS
28         PROGRAM_DEPENDS='SETUP_MANIFEST'
29         _program_exec_and_record_completion__operation ()
30         {
31                 message_section_title "Checking the paths of package files"
32                 while read -r cmd target argument additional
33                 do
34                         case $cmd in
35                                 add | addtool )
36                                         if ! pkgpath=`pkgsys_pkgname_to_pkgarc "$opt_packages_dir" "$target"`
37                                         then
38                                                 message_echo "ERROR: Package for [$target] is not found. Aborting." >&2
39                                                 exit 1
40                                         fi
41                                         additional=$pkgpath
42                                         ;;
43                                 delete | delete_pattern )
44                                         argument=NA
45                                         ;;
46                                 *)
47                                         message_echo "ERROR: Invalid command [$cmd] [$target] [$argument]" >&2
48                                         exit 1
49                         esac
50                         printf '%s\t%s\t%s\t%s\n' "$cmd" "$target" "$argument" "$additional"
51                 done < ${ETCDIR}/manifest.lst > ${DBDIR}/stage.loop_list/manifest_pkgpath
52                 cp /dev/null "${DBDIR}/stage.loop_list/failed_add"
53                 message_echo
54         }
55         program_exec_and_record_completion CHK_PKGS
56 }
57
58 # ============= (Re)installation of new and reinstalled ports =============
59 command_do_reinst_ports ()
60 {
61         local PROGRAM_DEPENDS
62         PROGRAM_DEPENDS='CHK_PKGS'
63         _program_exec_restartable_loop_operation__routine ()
64         {
65                 local cmd target argument additional target_regexp timestamp_init timestamp_fin pkgtype_init pkgtype_fin datetime_init datetime_fin origin target_pkg pkg pkg_pattern pkgpath item conflict pkgs_pkgtools
66                 cmd=`echo "$1" | cut -f 1`
67                 target=`echo "$1" | cut -f 2`
68                 argument=`echo "$1" | cut -f 3`
69                 additional=`echo "$1" | cut -f 4`
70                 target_regexp=`str_escape_regexp "$target"`
71                 timestamp_init=`grep -E "^${target_regexp}[[:space:]]" "${DBDIR}/initial_pkgs_snapshot.csv" | cut -f 2`
72                 timestamp_fin=`grep -E "^${target_regexp}[[:space:]]" "${ETCDIR}/final_pkgs_snapshot.csv" | cut -f 2`
73                 if [ -n "$timestamp_init" -a -n "$timestamp_fin" ]
74                 then
75                         pkgtype_init=`expr "$timestamp_init" : '\([^:]*\):' || :`
76                         pkgtype_fin=`expr "$timestamp_fin" : '\([^:]*\):' || :`
77                         if [ -n "$pkgtype_init" -a -n "$pkgtype_fin" -a "x$pkgtype_init" = "x$pkgtype_fin" ]
78                         then
79                                 datetime_init=`expr "$timestamp_init" : '[^:]*:\([0-9]*\)' || :`
80                                 datetime_fin=`expr "$timestamp_fin" : '[^:]*:\([0-9]*\)' || :`
81                                 [ -n "$datetime_init" -a -n "$datetime_fin" -a "$datetime_init" -ge "$datetime_fin" ] && return
82                         fi
83                 fi
84                 case $cmd in
85                         delete )
86                                 origin=$target
87                                 if pkgsys_exists_from_orig "$origin"
88                                 then
89                                         target_pkg=`pkgsys_get_installed_pkg_from_origin "$origin"`
90                                         if [ $opt_dry_run = yes ]
91                                         then
92                                                 message_echo "Dry run: Delete $target_pkg"
93                                         else
94                                                 message_echo "Deleting $target_pkg..."
95                                                 pkg_delete_f "$target_pkg" || \
96                                                         { message_echo "(Ignored)" >&2; }
97                                         fi
98                                 fi
99                                 ;;
100                         delete_pattern )
101                                 pkg_pattern=$target
102                                 pkgsys_get_installed_pkg_from_glob "$pkg_pattern" | while read pkgname
103                                 do
104                                         if [ $opt_dry_run = yes ]
105                                         then
106                                                 message_echo "Dry run: Delete $pkgname"
107                                         else
108                                                 message_echo "Deleting $pkgname..."
109                                                 pkg_delete_f "$pkgname" || \
110                                                         { message_echo "(Ignored)" >&2; }
111                                         fi
112                                 done
113                                 ;;
114                         add )
115                                 pkg=$target
116                                 pkgpath=$additional
117                                 if ! pkg_info_e "$pkg"
118                                 then
119                                         if [ $opt_dry_run = yes ]
120                                         then
121                                                 message_echo "Dry run: Add $pkgpath"
122                                         else
123                                                 if ! pkg_add_fF "$pkgpath"
124                                                 then
125                                                         message_echo "(Continue anyway)" >&2
126                                                         item=`printf '%s\t%s' "$pkg" "$pkgpath"`
127                                                         fileedit_add_a_line_if_new "$item" "${DBDIR}/stage.loop_list/failed_add"
128                                                 fi
129                                         fi
130                                 fi
131                                 ;;
132                         addtool )
133                                 pkgpath=$additional
134                                 origin=`expr "$argument" : '\([^|]*\)|'`
135                                 conflict=`expr "$argument" : '[^|]*|\(.*\)' | tr '|' '\n'`
136                                 pkgs_pkgtools=`{
137                                         echo "$conflict" | while read -r pkg_pattern
138                                         do
139                                                 [ -n "$pkg_pattern" ] || continue
140                                                 pkgsys_get_installed_pkg_from_glob "$pkg_pattern" || :
141                                         done
142                                         pkgsys_get_installed_pkg_from_origin "$origin"
143                                 } | sort -u`
144                                 if [ $opt_dry_run = yes ]
145                                 then
146                                         echo $pkgs_pkgtools | while read pkgname
147                                         do
148                                                 message_echo "Dry run: Delete $pkgname (package management tool)"
149                                         done
150                                         message_echo "Dry run: Add $pkgpath (package management tool)"
151                                 else
152                                         message_echo "Upgrading $pkgs_pkgtools..."
153                                         pkg_delete_f $pkgs_pkgtools || \
154                                                 { message_echo "(Ignored)" >&2; }
155                                         pkg_add_tools "$pkgpath" || pkg_rescue_tools
156                                 fi
157                                 ;;
158                 esac
159         }
160         _program_exec_and_record_completion__operation ()
161         {
162                 message_section_title "Smart update"
163                 pkg_rescue_tools
164                 program_exec_restartable_loop_operation manifest_pkgpath
165                 cp /dev/null "${DBDIR}/stage.loop_list/failed_add_again"
166                 message_echo
167         }
168         program_exec_and_record_completion SMART_UPDATE
169 }
170
171 # ============= Deinstallation of remaining old packages =============
172 # This may be needed if clean command was executed in the builder chroot environment.
173 command_do_deinst_remining_olg_pkgs ()
174 {
175         local PROGRAM_DEPENDS
176         PROGRAM_DEPENDS='SMART_UPDATE'
177         _program_exec_and_record_completion__operation ()
178         {
179                 message_section_title "Deinstalling remaining old packages if any..."
180                 pkg_get_pkgs_timestamps | \
181                         grep -vE "`pkgsys_pkgtools_pkgs_filter_regexp`"> ${TMPDIR}/current_pkgs_snapshot.csv
182                 grep -Fxv -f "${ETCDIR}/final_pkgs_snapshot.csv" "${TMPDIR}/current_pkgs_snapshot.csv" | \
183                         cut -f 1 | while read pkg_old
184                 do
185                         pkg_delete_f "$pkg_old"
186                 done
187                 message_echo
188         }
189         program_exec_and_record_completion DEINST_REMAINING_OLD_PKGS
190 }
191
192 # ============= Retrial of failed adding packages =============
193 command_do_retrial ()
194 {
195         local PROGRAM_DEPENDS
196         while [ `wc -l < ${DBDIR}/stage.loop_list/failed_add` -gt 0 ]
197         do
198                 rm -f  "${DBDIR}/RETRIAL_ADDING:restart"
199                 PROGRAM_DEPENDS='DEINST_REMAINING_OLD_PKGS'
200                 _program_exec_restartable_loop_operation__routine ()
201                 {
202                         local target pkgpath item
203                         target=`echo "$1" | cut -f 1`
204                         pkgpath=`echo "$1" | cut -f 2`
205                         if ! pkg_info_e "$target"
206                         then
207                                 if ! pkg_add_fF "$pkgpath"
208                                 then
209                                                 message_echo "(Continue anyway)" >&2
210                                                 item=`printf '%s\t%s' "$target" "$pkgpath"`
211                                                 fileedit_add_a_line_if_new "$item" "${DBDIR}/stage.loop_list/failed_add_again"
212                                 fi
213                         fi
214                 }
215                 _program_exec_and_record_completion__operation ()
216                 {
217                         message_section_title "Retrial of failed installation"
218                         program_exec_restartable_loop_operation failed_add
219                         touch "${DBDIR}/stage.loop_list/failed_add_again"
220                         if [ `wc -l < ${DBDIR}/stage.loop_list/failed_add_again` -eq 0 ] || diff -q "${DBDIR}/stage.loop_list/failed_add_again" "${DBDIR}/stage.loop_list/failed_add" > /dev/null 2>/dev/null
221                         then
222                                 cp /dev/null "${DBDIR}/stage.loop_list/failed_add"
223                         else
224                                 touch "${DBDIR}/RETRIAL_ADDING:restart"
225                                 mv "${DBDIR}/stage.loop_list/failed_add_again" "${DBDIR}/stage.loop_list/failed_add"
226                                 touch "${DBDIR}/stage.loop_list/failed_add_again"
227                         fi
228                         message_echo
229                 }
230                 program_exec_and_record_completion RETRIAL_ADDING
231                 [ -e "${DBDIR}/RETRIAL_ADDING:restart" ] && program_reset_loop_for_stage RETRIAL_ADDING
232         done
233 }
234
235 # ============= Main operation of do =============
236 command_do_main ()
237 {
238         # Set up the manifest
239         command_do_setup_manifest
240
241         # Check of package paths
242         command_do_chk_pkg_paths
243
244         # (Re)installation of new and reinstalled ports
245         command_do_reinst_ports
246
247         # Retrial of failed adding packages
248         [ $opt_dry_run = yes ] || command_do_retrial
249 }
250
251 # ============= Notice of failure =============
252 command_do_failure_notice ()
253 {
254         touch "${DBDIR}/stage.loop_list/failed_add_again"
255         if [ `wc -l < ${DBDIR}/stage.loop_list/failed_add_again` -gt 0 ]
256         then
257                 message_echo "ERROR: The following packages failed to (re)install." >&2
258                 ${DBDIR}/stage.loop_list/failed_add_again | cut -f 1 | message_cat >&2
259                 exit 1
260         fi
261 }
262
263 # ============= Ending process =============
264 command_do_ending_process ()
265 {
266         command_do_failure_notice
267         temp_terminate_process () { :; }
268         if [ $opt_no_opening_message = yes ]
269         then
270                 message_echo "Done as ${APPNAME}"
271                 return
272         fi
273         message_section_title "COMPLETELY DONE"
274         message_echo "- E N D -"
275 }