]> git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/Source/Python/UPT/RmPkg.py
BaseTools:Update mailing list address in BaseTools error messages
[mirror_edk2.git] / BaseTools / Source / Python / UPT / RmPkg.py
1 ## @file
2 # Install distribution package.
3 #
4 # Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
5 #
6 # SPDX-License-Identifier: BSD-2-Clause-Patent
7 #
8
9 '''
10 RmPkg
11 '''
12
13 ##
14 # Import Modules
15 #
16 import os.path
17 from stat import S_IWUSR
18 from traceback import format_exc
19 from platform import python_version
20 from hashlib import md5
21 from sys import stdin
22 from sys import platform
23
24 from Core.DependencyRules import DependencyRules
25 from Library import GlobalData
26 from Logger import StringTable as ST
27 import Logger.Log as Logger
28 from Logger.ToolError import OPTION_MISSING
29 from Logger.ToolError import UNKNOWN_ERROR
30 from Logger.ToolError import ABORT_ERROR
31 from Logger.ToolError import CODE_ERROR
32 from Logger.ToolError import FatalError
33
34
35 ## CheckDpDepex
36 #
37 # Check if the Depex is satisfied
38 # @param Dep: Dep
39 # @param Guid: Guid of Dp
40 # @param Version: Version of Dp
41 # @param WorkspaceDir: Workspace Dir
42 #
43 def CheckDpDepex(Dep, Guid, Version, WorkspaceDir):
44 (Removable, DependModuleList) = Dep.CheckDpDepexForRemove(Guid, Version)
45 if not Removable:
46 Logger.Info(ST.MSG_CONFIRM_REMOVE)
47 Logger.Info(ST.MSG_USER_DELETE_OP)
48 Input = stdin.readline()
49 Input = Input.replace('\r', '').replace('\n', '')
50 if Input.upper() != 'Y':
51 Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_USER_INTERRUPT)
52 return 1
53 else:
54 #
55 # report list of modules that are not valid due to force
56 # remove,
57 # also generate a log file for reference
58 #
59 Logger.Info(ST.MSG_INVALID_MODULE_INTRODUCED)
60 LogFilePath = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gINVALID_MODULE_FILE))
61 Logger.Info(ST.MSG_CHECK_LOG_FILE % LogFilePath)
62 try:
63 LogFile = open(LogFilePath, 'w')
64 try:
65 for ModulePath in DependModuleList:
66 LogFile.write("%s\n"%ModulePath)
67 Logger.Info(ModulePath)
68 except IOError:
69 Logger.Warn("\nRmPkg", ST.ERR_FILE_WRITE_FAILURE,
70 File=LogFilePath)
71 except IOError:
72 Logger.Warn("\nRmPkg", ST.ERR_FILE_OPEN_FAILURE,
73 File=LogFilePath)
74 finally:
75 LogFile.close()
76
77 ## Remove Path
78 #
79 # removing readonly file on windows will get "Access is denied"
80 # error, so before removing, change the mode to be writeable
81 #
82 # @param Path: The Path to be removed
83 #
84 def RemovePath(Path):
85 Logger.Info(ST.MSG_REMOVE_FILE % Path)
86 if not os.access(Path, os.W_OK):
87 os.chmod(Path, S_IWUSR)
88 os.remove(Path)
89 try:
90 os.removedirs(os.path.split(Path)[0])
91 except OSError:
92 pass
93 ## GetCurrentFileList
94 #
95 # @param DataBase: DataBase of UPT
96 # @param Guid: Guid of Dp
97 # @param Version: Version of Dp
98 # @param WorkspaceDir: Workspace Dir
99 #
100 def GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir):
101 NewFileList = []
102 for Dir in DataBase.GetDpInstallDirList(Guid, Version):
103 RootDir = os.path.normpath(os.path.join(WorkspaceDir, Dir))
104 for Root, Dirs, Files in os.walk(RootDir):
105 Logger.Debug(0, Dirs)
106 for File in Files:
107 FilePath = os.path.join(Root, File)
108 if FilePath not in NewFileList:
109 NewFileList.append(FilePath)
110 return NewFileList
111
112
113 ## Tool entrance method
114 #
115 # This method mainly dispatch specific methods per the command line options.
116 # If no error found, return zero value so the caller of this tool can know
117 # if it's executed successfully or not.
118 #
119 # @param Options: command option
120 #
121 def Main(Options = None):
122
123 try:
124 DataBase = GlobalData.gDB
125 if not Options.DistributionFile:
126 Logger.Error("RmPkg",
127 OPTION_MISSING,
128 ExtraData=ST.ERR_SPECIFY_PACKAGE)
129 WorkspaceDir = GlobalData.gWORKSPACE
130 #
131 # Prepare check dependency
132 #
133 Dep = DependencyRules(DataBase)
134
135 #
136 # Get the Dp information
137 #
138 StoredDistFile, Guid, Version = GetInstalledDpInfo(Options.DistributionFile, Dep, DataBase, WorkspaceDir)
139
140 #
141 # Check Dp depex
142 #
143 CheckDpDepex(Dep, Guid, Version, WorkspaceDir)
144
145 #
146 # remove distribution
147 #
148 RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, Options.Yes)
149
150 Logger.Quiet(ST.MSG_FINISH)
151
152 ReturnCode = 0
153
154 except FatalError as XExcept:
155 ReturnCode = XExcept.args[0]
156 if Logger.GetLevel() <= Logger.DEBUG_9:
157 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
158 format_exc())
159 except KeyboardInterrupt:
160 ReturnCode = ABORT_ERROR
161 if Logger.GetLevel() <= Logger.DEBUG_9:
162 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
163 format_exc())
164 except:
165 Logger.Error(
166 "\nRmPkg",
167 CODE_ERROR,
168 ST.ERR_UNKNOWN_FATAL_REMOVING_ERR,
169 ExtraData=ST.MSG_SEARCH_FOR_HELP % ST.MSG_EDKII_MAIL_ADDR,
170 RaiseError=False
171 )
172 Logger.Quiet(ST.MSG_PYTHON_ON % (python_version(), platform) + \
173 format_exc())
174 ReturnCode = CODE_ERROR
175 return ReturnCode
176
177 ## GetInstalledDpInfo method
178 #
179 # Get the installed distribution information
180 #
181 # @param DistributionFile: the name of the distribution
182 # @param Dep: the instance of DependencyRules
183 # @param DataBase: the internal database
184 # @param WorkspaceDir: work space directory
185 # @retval StoredDistFile: the distribution file that backed up
186 # @retval Guid: the Guid of the distribution
187 # @retval Version: the Version of distribution
188 #
189 def GetInstalledDpInfo(DistributionFile, Dep, DataBase, WorkspaceDir):
190 (Guid, Version, NewDpFileName) = DataBase.GetDpByName(os.path.split(DistributionFile)[1])
191 if not Guid:
192 Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_PACKAGE_NOT_INSTALLED % DistributionFile)
193
194 #
195 # Check Dp existing
196 #
197 if not Dep.CheckDpExists(Guid, Version):
198 Logger.Error("RmPkg", UNKNOWN_ERROR, ST.ERR_DISTRIBUTION_NOT_INSTALLED)
199 #
200 # Check for Distribution files existence in /conf/upt, if not exist,
201 # Warn user and go on.
202 #
203 StoredDistFile = os.path.normpath(os.path.join(WorkspaceDir, GlobalData.gUPT_DIR, NewDpFileName))
204 if not os.path.isfile(StoredDistFile):
205 Logger.Warn("RmPkg", ST.WRN_DIST_NOT_FOUND%StoredDistFile)
206 StoredDistFile = None
207
208 return StoredDistFile, Guid, Version
209
210 ## RemoveDist method
211 #
212 # remove a distribution
213 #
214 # @param Guid: the Guid of the distribution
215 # @param Version: the Version of distribution
216 # @param StoredDistFile: the distribution file that backed up
217 # @param DataBase: the internal database
218 # @param WorkspaceDir: work space directory
219 # @param ForceRemove: whether user want to remove file even it is modified
220 #
221 def RemoveDist(Guid, Version, StoredDistFile, DataBase, WorkspaceDir, ForceRemove):
222 #
223 # Get Current File List
224 #
225 NewFileList = GetCurrentFileList(DataBase, Guid, Version, WorkspaceDir)
226
227 #
228 # Remove all files
229 #
230 MissingFileList = []
231 for (Path, Md5Sum) in DataBase.GetDpFileList(Guid, Version):
232 if os.path.isfile(Path):
233 if Path in NewFileList:
234 NewFileList.remove(Path)
235 if not ForceRemove:
236 #
237 # check whether modified by users
238 #
239 Md5Signature = md5(open(str(Path), 'rb').read())
240 if Md5Sum != Md5Signature.hexdigest():
241 Logger.Info(ST.MSG_CONFIRM_REMOVE2 % Path)
242 Input = stdin.readline()
243 Input = Input.replace('\r', '').replace('\n', '')
244 if Input.upper() != 'Y':
245 continue
246 RemovePath(Path)
247 else:
248 MissingFileList.append(Path)
249
250 for Path in NewFileList:
251 if os.path.isfile(Path):
252 if (not ForceRemove) and (not os.path.split(Path)[1].startswith('.')):
253 Logger.Info(ST.MSG_CONFIRM_REMOVE3 % Path)
254 Input = stdin.readline()
255 Input = Input.replace('\r', '').replace('\n', '')
256 if Input.upper() != 'Y':
257 continue
258 RemovePath(Path)
259
260 #
261 # Remove distribution files in /Conf/.upt
262 #
263 if StoredDistFile is not None:
264 os.remove(StoredDistFile)
265
266 #
267 # update database
268 #
269 Logger.Quiet(ST.MSG_UPDATE_PACKAGE_DATABASE)
270 DataBase.RemoveDpObj(Guid, Version)