@@ -10,6 +10,7 @@ package system
1010
1111import (
1212 "bytes"
13+ "encoding/json"
1314 "errors"
1415 "fmt"
1516 "os"
@@ -200,8 +201,101 @@ func QueryPackageDownloadSize(updateType UpdateType, packages ...string) (float6
200201 return * downloadSize , * allPackageSize , nil
201202}
202203
203- // QuerySourceDownloadSize 根据更新类型(仓库),获取需要的下载量,return arg0:需要下载的量;arg1:所有包的大小;arg2:error
204+ // queryDownloadSizeViaApt queries the download size information by running apt-get dist-upgrade
205+ // with the given source path. It parses the command output to extract package size data.
206+ // Returns: bytes needed to download, total size of all packages, error.
207+ func queryDownloadSizeViaApt (path string , updateType UpdateType , pkgList []string ) (float64 , float64 , error ) {
208+ var cmd * exec.Cmd
209+ if utils2 .IsDir (path ) {
210+ // #nosec G204
211+ cmd = exec .Command ("/usr/bin/apt-get" ,
212+ append ([]string {"dist-upgrade" , "-d" , "-o" , "Debug::NoLocking=1" , "-c" , LastoreAptV2CommonConfPath , "--assume-no" ,
213+ "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::sourcelist" , "/dev/null" ),
214+ "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::SourceParts" , path )}, pkgList ... )... )
215+ } else {
216+ // #nosec G204
217+ cmd = exec .Command ("/usr/bin/apt-get" ,
218+ append ([]string {"dist-upgrade" , "-d" , "-o" , "Debug::NoLocking=1" , "-c" , LastoreAptV2CommonConfPath , "--assume-no" ,
219+ "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::sourcelist" , path ),
220+ "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::SourceParts" , "/dev/null" )}, pkgList ... )... )
221+ }
222+ cmd .Env = append (os .Environ (), "LC_ALL=C" )
223+ logger .Infof ("%v download size cmd: %v" , updateType .JobType (), cmd .String ())
224+ lines , err := utils .FilterExecOutput (cmd , time .Second * 120 , func (line string ) bool {
225+ _ , _ , _err := parsePackageSize (line )
226+ return _err == nil
227+ })
228+ if err != nil && len (lines ) == 0 {
229+ return 0 , 0 , fmt .Errorf ("run:%v failed-->%v" , cmd .Args , err )
230+ }
231+ if len (lines ) != 0 {
232+ needDownloadSize , allSize , err := parsePackageSize (lines [0 ])
233+ if err != nil {
234+ logger .Warning (err )
235+ return 0 , 0 , err
236+ }
237+ return needDownloadSize , allSize , nil
238+ }
239+ return 0 , 0 , nil
240+ }
241+
242+ // immutableUpgradeCheckOutput represents the JSON output of deepin-immutable-ctl upgrade check -j.
243+ type immutableUpgradeCheckOutput struct {
244+ Code int `json:"code"`
245+ Message string `json:"message"`
246+ Data struct {
247+ TotalSize int64 `json:"totalSize"`
248+ CachedOstreePkgCount int64 `json:"cachedOstreePkgCount"`
249+ NeedDownload struct {
250+ Size int64 `json:"size"`
251+ } `json:"needDownload"`
252+ } `json:"data"`
253+ }
254+
255+ // queryDownloadSizeForImmutable queries the download size information for immutable systems
256+ // by invoking deepin-immutable-ctl upgrade check. The source path is passed via the
257+ // DEEPIN_IMMUTABLE_UPGRADE_APT_OPTION environment variable.
258+ // Returns: bytes needed to download, total size of all packages, error.
259+ func queryDownloadSizeForImmutable (path string , updateType UpdateType , pkgList []string ) (float64 , float64 , error ) {
260+ var sourceArgs string
261+ cmd := exec .Command (DeepinImmutableCtlPath , "upgrade" , "check" , "-j" )
262+ if path != "" {
263+ if utils2 .IsDir (path ) {
264+ sourceArgs = "-o Dir::Etc::sourcelist=/dev/null -o Dir::Etc::SourceParts=" + path
265+ } else {
266+ sourceArgs = "-o Dir::Etc::sourcelist=" + path + " -o Dir::Etc::SourceParts=/dev/null"
267+ }
268+ }
269+ cmd .Env = append (os .Environ (), "LC_ALL=C" ,
270+ "DEEPIN_IMMUTABLE_UPGRADE_APT_OPTION=" + sourceArgs )
271+ logger .Infof ("%v download size cmd (immutable): %v" , updateType .JobType (), cmd .String ())
272+ out , err := cmd .Output ()
273+ logger .Debugf ("immutable upgrade check output: %s" , out )
274+ if err != nil {
275+ return 0 , 0 , fmt .Errorf ("run %v failed: %v" , cmd .Args , err )
276+ }
277+ var result immutableUpgradeCheckOutput
278+ if err := json .Unmarshal (out , & result ); err != nil {
279+ return 0 , 0 , fmt .Errorf ("parse immutable upgrade check output failed: %v" , err )
280+ }
281+ logger .Debugf ("immutable upgrade check result: %+v" , result )
282+ if result .Code != 0 {
283+ return 0 , 0 , fmt .Errorf ("immutable upgrade check returned code %d: %s" , result .Code , result .Message )
284+ }
285+ needDownload := result .Data .NeedDownload .Size
286+ totalSize := result .Data .TotalSize
287+ if needDownload == 0 && totalSize == 0 && result .Data .CachedOstreePkgCount > 0 {
288+ // TODO 此时如果返回 0, 0, nil 会导致控制中心界面卡住。
289+ return 0 , 1 , nil
290+ }
291+ return float64 (needDownload ), float64 (totalSize ), nil
292+ }
293+
294+ // QuerySourceDownloadSize returns the download size information for the given update type.
295+ // It selects the appropriate backend (apt or immutable-ctl) based on the IncrementalUpdate flag.
296+ // Returns: bytes needed to download, total size of all packages, error.
204297func QuerySourceDownloadSize (updateType UpdateType , pkgList []string ) (float64 , float64 , error ) {
298+ logger .Debugf ("QuerySourceDownloadSize updateType: %v, pkgList: %v" , updateType , pkgList )
205299 startTime := time .Now ()
206300 downloadSize := new (float64 )
207301 allPackageSize := new (float64 )
@@ -211,46 +305,24 @@ func QuerySourceDownloadSize(updateType UpdateType, pkgList []string) (float64,
211305 unref ()
212306 }
213307 }()
214- var cmd * exec.Cmd
215- if utils2 .IsDir (path ) {
216- // #nosec G204
217- cmd = exec .Command ("/usr/bin/apt-get" ,
218- append ([]string {"dist-upgrade" , "-d" , "-o" , "Debug::NoLocking=1" , "-c" , LastoreAptV2CommonConfPath , "--assume-no" ,
219- "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::sourcelist" , "/dev/null" ),
220- "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::SourceParts" , path )}, pkgList ... )... )
221- } else {
222- // #nosec G204
223- cmd = exec .Command ("/usr/bin/apt-get" ,
224- append ([]string {"dist-upgrade" , "-d" , "-o" , "Debug::NoLocking=1" , "-c" , LastoreAptV2CommonConfPath , "--assume-no" ,
225- "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::sourcelist" , path ),
226- "-o" , fmt .Sprintf ("%v=%v" , "Dir::Etc::SourceParts" , "/dev/null" )}, pkgList ... )... )
227- }
228- cmd .Env = append (os .Environ (), "LC_ALL=C" )
229- logger .Infof ("%v download size cmd: %v" , updateType .JobType (), cmd .String ())
230- lines , err := utils .FilterExecOutput (cmd , time .Second * 120 , func (line string ) bool {
231- _ , _ , _err := parsePackageSize (line )
232- return _err == nil
233- })
234- if err != nil && len (lines ) == 0 {
235- return fmt .Errorf ("run:%v failed-->%v" , cmd .Args , err )
308+ queryFn := queryDownloadSizeViaApt
309+ if IncrementalUpdate {
310+ queryFn = queryDownloadSizeForImmutable
236311 }
237-
238- if len (lines ) != 0 {
239- needDownloadSize , allSize , err := parsePackageSize (lines [0 ])
240- if err != nil {
241- logger .Warning (err )
242- return err
243- }
244- * downloadSize = needDownloadSize
245- * allPackageSize = allSize
312+ needDownloadSize , allSize , err := queryFn (path , updateType , pkgList )
313+ if err != nil {
314+ return err
246315 }
316+ * downloadSize = needDownloadSize
317+ * allPackageSize = allSize
247318 return nil
248319 })
249320 if err != nil {
250321 logger .Warning (err )
251322 return SizeDownloaded , SizeDownloaded , err
252323 }
253324 logger .Debug ("end QuerySourceDownloadSize duration:" , time .Now ().Sub (startTime ))
325+ logger .Debugf ("QuerySourceDownloadSize result, download size: %v, all package size: %v" , * downloadSize , * allPackageSize )
254326 return * downloadSize , * allPackageSize , nil
255327}
256328
@@ -329,7 +401,7 @@ func QuerySourceAddSize(updateType UpdateType) (float64, error) {
329401 logger .Warning (err )
330402 return SizeUnknown , err
331403 }
332- logger .Debug ("end QuerySourceDownloadSize duration:" , time .Now ().Sub (startTime ))
404+ logger .Debug ("end QuerySourceAddSize duration:" , time .Now ().Sub (startTime ))
333405 return * addSize , nil
334406}
335407
0 commit comments