@@ -10,6 +10,7 @@ package system
1010
1111import (
1212 "bytes"
13+ "encoding/json"
1314 "errors"
1415 "fmt"
1516 "os"
@@ -200,8 +201,107 @@ 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 uint64 `json:"totalSize"`
248+ CachedOstreePkgCount int `json:"cachedOstreePkgCount"`
249+ NeedDownload struct {
250+ Size uint64 `json:"size"`
251+ } `json:"needDownload"`
252+ } `json:"data"`
253+ }
254+
255+ // queryDownloadSizeForIncrementalUpdate queries the download size information for incremental updates
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 queryDownloadSizeForIncrementalUpdate (path string , updateType UpdateType , pkgList []string ) (float64 , float64 , error ) {
260+ var sourceArgs string
261+ modeStr := updateType .JobType ()
262+ if modeStr == "" {
263+ modeStr = fmt .Sprintf ("mode-%d" , updateType )
264+ }
265+ cmd := exec .Command (DeepinImmutableCtlPath , "upgrade" , "check" , "-j" , "-m" , modeStr )
266+ if path != "" {
267+ if utils2 .IsDir (path ) {
268+ sourceArgs = "-o Dir::Etc::sourcelist=/dev/null -o Dir::Etc::SourceParts=" + path
269+ } else {
270+ sourceArgs = "-o Dir::Etc::sourcelist=" + path + " -o Dir::Etc::SourceParts=/dev/null"
271+ }
272+ }
273+ cmd .Env = append (os .Environ (), "LC_ALL=C" ,
274+ "DEEPIN_IMMUTABLE_UPGRADE_APT_OPTION=" + sourceArgs )
275+ logger .Infof ("%v download size cmd: %v, sourceArgs: %v" , updateType .JobType (), cmd .String (), sourceArgs )
276+ out , err := cmd .Output ()
277+ logger .Debugf ("immutable upgrade check output: %s" , out )
278+ if err != nil {
279+ return 0 , 0 , fmt .Errorf ("run %v failed: %v" , cmd .Args , err )
280+ }
281+ var result immutableUpgradeCheckOutput
282+ if err := json .Unmarshal (out , & result ); err != nil {
283+ return 0 , 0 , fmt .Errorf ("parse immutable upgrade check output failed: %v" , err )
284+ }
285+ logger .Debugf ("immutable upgrade check result: %+v" , result )
286+ if result .Code != 0 {
287+ return 0 , 0 , fmt .Errorf ("immutable upgrade check returned code %d: %s" , result .Code , result .Message )
288+ }
289+ needDownload := result .Data .NeedDownload .Size
290+ totalSize := result .Data .TotalSize
291+ // If both needDownload and totalSize are 0 but cached ostree packages exist, the ostree
292+ // transfer stats have likely been discarded. Return a non-zero totalSize (1) as a
293+ // sentinel to prevent the control center upgrade UI from stalling on a zero-size result.
294+ if needDownload == 0 && totalSize == 0 && result .Data .CachedOstreePkgCount > 0 {
295+ return 0 , 1 , nil
296+ }
297+ return float64 (needDownload ), float64 (totalSize ), nil
298+ }
299+
300+ // QuerySourceDownloadSize returns the download size information for the given update type.
301+ // It selects the appropriate backend (apt or immutable-ctl) based on the IncrementalUpdate flag.
302+ // Returns: bytes needed to download, total size of all packages, error.
204303func QuerySourceDownloadSize (updateType UpdateType , pkgList []string ) (float64 , float64 , error ) {
304+ logger .Debugf ("QuerySourceDownloadSize updateType: %v, pkgList: %v" , updateType , pkgList )
205305 startTime := time .Now ()
206306 downloadSize := new (float64 )
207307 allPackageSize := new (float64 )
@@ -211,46 +311,25 @@ func QuerySourceDownloadSize(updateType UpdateType, pkgList []string) (float64,
211311 unref ()
212312 }
213313 }()
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 )
314+ queryFn := queryDownloadSizeViaApt
315+ if IncrementalUpdate {
316+ queryFn = queryDownloadSizeForIncrementalUpdate
236317 }
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
318+ needDownloadSize , allSize , err := queryFn (path , updateType , pkgList )
319+ if err != nil {
320+ return err
246321 }
322+ * downloadSize = needDownloadSize
323+ * allPackageSize = allSize
247324 return nil
248325 })
249326 if err != nil {
250327 logger .Warning (err )
251328 return SizeDownloaded , SizeDownloaded , err
252329 }
253330 logger .Debug ("end QuerySourceDownloadSize duration:" , time .Now ().Sub (startTime ))
331+ logger .Debugf ("QuerySourceDownloadSize result, download size: %s, all package size: %s" ,
332+ utils .FormatSize (* downloadSize ), utils .FormatSize (* allPackageSize ))
254333 return * downloadSize , * allPackageSize , nil
255334}
256335
@@ -329,7 +408,7 @@ func QuerySourceAddSize(updateType UpdateType) (float64, error) {
329408 logger .Warning (err )
330409 return SizeUnknown , err
331410 }
332- logger .Debug ("end QuerySourceDownloadSize duration:" , time .Now ().Sub (startTime ))
411+ logger .Debug ("end QuerySourceAddSize duration:" , time .Now ().Sub (startTime ))
333412 return * addSize , nil
334413}
335414
0 commit comments