From: Chulwoo Shin Date: Fri, 21 Apr 2017 04:56:46 +0000 (+0900) Subject: [TIC-Web] fix the issue that cannot analyze install-dependency X-Git-Tag: v20170428~9^2~2^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c9b779608505d360f51bc2b712e3ff93f32e4827;p=archive%2F20170607%2Ftools%2Ftic.git [TIC-Web] fix the issue that cannot analyze install-dependency - fix the issue that cannot analyze install-dependency - support the recommends tag Change-Id: I456e83a7195605961423c0b378841d6024c586b6 Signed-off-by: Chulwoo Shin --- diff --git a/public/src/js/page/package.js b/public/src/js/page/package.js index 2f72976..dd2a856 100644 --- a/public/src/js/page/package.js +++ b/public/src/js/page/package.js @@ -40,14 +40,16 @@ define([ var $tree = $('#tic-package-left-col-tree'); var defaultFilters = []; - var repos = []; - var packages = []; - var pkgInfo = null; - var provides = null; - var files = null; - var conflicts = null; - var groups = null; - var groupId = 0; + let repos = []; + let packages = []; + let pkgInfo = null; + let provides = null; + let files = null; + let groups = null; + let groupId = 0; + let conflicts = null; + let selfCheckedMap = {}; + let requiredInstPkgs = null; //To manage that the image creation var micMgr = []; @@ -218,10 +220,13 @@ define([ } } - function _setDefaultPackage(defaultPackages) { + function _setDefaultPackage(installPackages) { var nodes = [] - var pickDefault = _.pick(pkgInfo, defaultPackages); + var pickDefault = _.pick(pkgInfo, installPackages); _.forEach(pickDefault, function(value, key) { + if (value.selfChecked === true) { + selfCheckedMap[key] = value; + } // One or more of the same nodes can exist _.forEach(value.view, function(node) { nodes.push(node); @@ -355,267 +360,494 @@ define([ } } - // analyze install-dependency (requires) - function _analyzeInstallDependency(checkNode) { - var stack = []; - var pkg_count = Object.keys(pkgInfo).length - var number = 0; - var sccNum = 0; - var groupNum = 0; - var selected = new Array(pkg_count); - var scc_id = new Array(pkg_count); - var min_num = new Array(pkg_count); - var progressStatus = true; - var errorMsg = null; - var conflictsTable = {}; - - // init check type - _.forEach(pkgInfo, function(value, key) { - // check type: -1(unchecked), 0(checked), 1~N(checking) - selected[value.id] = value.checked ? 0 : -1; - scc_id[value.id] = 0; - }); - - function _makeSCC(pkgId) { - sccNum += 1; - var sccList = []; - - // make scc - while(!_.isEmpty(stack)) { - var pkg = stack.pop(); - scc_id[pkg.id] = sccNum; - sccList.push(pkg); - - if (pkg.id === pkgId) { - break; + function _checkConflicts(node, selected) { + var ret = {'result': false, 'message': null, 'conflictPkg': null}; + // 1. Check whether node can be installed + if (!_.isEmpty(node.provides)) { + _.forEach(node.provides, function(provide) { + if (!_.isEmpty(conflicts[provide.name])) { + _.forEach(conflicts[provide.name], function(conflict) { + // compare version between conflict with provide + if (!conflict.data.ver || _meetRequiredVersion(conflict.data, provide)) { + // package conflict + logger.info('[Conflict] The "' + node.name + '" is conflict with "' + conflict.name + '"'); + ret.message = 'The "' + node.name + '" is conflict with "' + conflict.name + '"'; + ret.result = true; + ret.conflictPkg = pkgInfo[conflict.name]; + return false; + } + }); } - } - - // circular depependency - if (sccList.length > 1) { - groupId += 1; - var groupPkgList = []; - _.forEach(sccList, function(pkg) { - pkg.group = groupId; - groupPkgList.push(pkg.name); - }); - groups[groupId] = groupPkgList; - // logger.info('circular dependency: groupId(' + groupId + '), list(' + groupPkgList + ')'); - } + if (ret.result === true) { + return false; + } + }); } - function _createReference(node1, node2) { - if (!_.isEmpty(node1.forward) && _.includes(node1.forward, node2.name)) - return + // 2. If the conflict package defined by node is installed + if (ret.result === false && !_.isEmpty(node.conflicts)) { + _.forEach(node.conflicts, function(conflict) { + if (conflict.name in provides) { + _.forEach(provides[conflict.name], function(provide) { + pkg = pkgInfo[provide.name]; + if (selected[pkg.id] !== -1) { + if (!conflict.ver || _meetRequiredVersion(conflict, provide.data)) { + // package conflicts + logger.info('[Conflict] The "' + provide.name + '" is conflict with "' + node.name + '"'); + ret.message = 'The "'+provide.name+'" is conflict with "'+node.name + '"'; + ret.result = true; + ret.conflictPkg = pkg; + return false; + } + } + }); + } else if (conflict.name in pkgInfo) { + var pkg = pkgInfo[conflict.name]; + if (selected[pkg.id] !== -1) { + if (!conflict.ver || _meetRequiredVersion(conflict, pkg.version)) { + // package conflicts + logger.info('[Conflict] The "' + pkg.name + '" is conflit with "' + node.name + '"'); + ret.message = 'The "' + pkg.name +'" is conflict with "' + node.name + '"'; + ret.result = true; + ret.conflictPkg = pkg + return false; + } + } + } + if (ret.result === true) { + return false; + } + }); + } + return ret; + } - if (!_.isEmpty(node1.forward)) { - node1.forward.push(node2.name); - } else { - node1.forward = [node2.name]; + function _select_files(require, selected) { + if (_.isEmpty(require) || _.isEmpty(files[require.name])) { + return null; + } + var selectpkg = null; + // 1. sort in ascending order + var fileList = files[require.name]; + fileList.sort(); + // 2-1. Choose the selected rpm + for (let fname of fileList) { + let fileInfo = pkgInfo[fname]; + if ((fname in requiredInstPkgs) || selected[fileInfo.id] !== -1) { + return fileInfo; } - - if (!_.isEmpty(node2.backward)) { - node2.backward.push(node1.name); - } else { - node2.backward = [node1.name]; + } + // 2-2. Choose the rpm (it does not conflitcs) + for (let fname of fileList) { + let fileInfo = pkgInfo[fname]; + var checkConflict = _checkConflicts(fileInfo, selected); + if (checkConflict.result === false) { + return fileInfo; } } + return pkgInfo[fileList[0]]; + } - function _select_files(fileList, require) { - if (!fileList || !require){ - return null; - } - var selectpkg = null; - // 1. sort in ascending order - fileList.sort(); - // 2-1. Choose the selected rpm - for (let fname of fileList) { - let fileInfo = pkgInfo[fname]; - if (fileInfo.checked || selected[fileInfo.id] >= 1) { - return fileInfo; + function _select_rpm(require, selected, recommend) { + if (_.isEmpty(require) || _.isEmpty(provides[require.name])) { + return null; + } + var capability = provides[require.name]; + var provideList = []; + // 1. Choose the rpm included in version from provides + if (require.ver) { + _.forEach(capability, function(provide) { + var verData = provide.data; + if(!provide.data.ver) { + var pkg = pkgInfo[provide.name]; + verData = pkg.version; } - } - // 2-2. Choose the rpm (it does not conflitcs) - for (let fname of fileList) { - let fileInfo = pkgInfo[fname]; - var checkConflict = _checkConflicts(fileInfo); - if (checkConflict.result === false) { - return fileInfo; + if (_meetRequiredVersion(require, verData)) { + // Meet the required version + provideList.push(provide); } - } - return pkgInfo[fileList[0]]; - } - - function _select_rpm(capability, require, recommend) { - var provideList = []; - // 1. Choose the rpm included in version from provides - if (require.ver) { - _.forEach(capability, function(provide) { - var verData = provide.data; - if(!provide.data.ver) { - var pkg = pkgInfo[provide.name]; - verData = pkg.version; - } - if (_meetRequiredVersion(require, verData)) { - // Meet the required version - provideList.push(provide); - } - }); - } else { - provideList = capability; - } + }); + } else { + provideList = capability; + } - // error case (the rpm does not exist) - if (_.isEmpty(provideList)) { - return null; - } + // error case (the rpm does not exist) + if (_.isEmpty(provideList)) { + return null; + } - if (provideList.length === 1) { - return pkgInfo[provideList[0].name]; - } + if (provideList.length === 1) { + return pkgInfo[provideList[0].name]; + } - // 2. Select one of the rpms by priority - // 2-1. Choose the default rpm or the selected rpm - for (var provide of provideList) { - var tmpInfo = pkgInfo[provide.name]; - if (tmpInfo.checked || selected[tmpInfo.id] >= 1) { - return tmpInfo; - } + // 2. Select one of the rpms by priority + // 2-1. Choose the default rpm or the selected rpm + for (var provide of provideList) { + var candidatePkg = pkgInfo[provide.name]; + if ((provide.name in requiredInstPkgs) || selected[candidatePkg.id] !== -1) { + return candidatePkg; } - // 2-2. Choose the rpm of default profile - // TODO: should be supported - - // 2-3. Choose recommends pkg (pkg-name or capability) - if (recommend) { - for (let provide of provideList) { - let provide_info = pkgInfo[provide.name]; - for (var reco of recommend) { - // 2-3-1. select a pkg that is named - if (reco.name == provide_info.name) { + } + // 2-2. Choose the rpm of default profile + // TODO: should be supported + + // 2-3. Choose recommends pkg (pkg-name or capability) + if (recommend) { + for (let provide of provideList) { + let provide_info = pkgInfo[provide.name]; + for (var reco of recommend) { + // 2-3-1. select a pkg that is named + if (reco.name == provide_info.name) { + return provide_info; + } + // 2-3-2. select a pkg that provides + for (var cap of provide_info['provides']) { + if (reco.name == cap.name) { return provide_info; } - // 2-3-2. select a pkg that provides - for (var cap of provide_info['provides']) { - if (reco.name == cap.name) { - return provide_info; - } - } } } } - var maxVersion = null; - // 2-4. Select the latest version of rpm - _.forEach (provideList, function(provide) { - var checkConflict = _checkConflicts(pkgInfo[provide.name]); - if (checkConflict.result === false) { - if (maxVersion) { - var ret = _comapre_ver(maxVersion.data, provide.data) - // version equals - if (ret === 0) { - // string compare - if (maxVersion.name > provide.name) { - maxVersion = provide; - } - } else if (ret === -1) { - // greater than maxVersion + } + var maxVersion = null; + // 2-4. Select the latest version of rpm + _.forEach (provideList, function(provide) { + var checkConflict = _checkConflicts(pkgInfo[provide.name], selected); + if (checkConflict.result === false) { + if (maxVersion) { + var ret = _comapre_ver(maxVersion.data, provide.data) + // version equals + if (ret === 0) { + // string compare + if (maxVersion.name > provide.name) { maxVersion = provide; } - } else { + } else if (ret === -1) { + // greater than maxVersion maxVersion = provide; } + } else { + maxVersion = provide; + } + } + }); + + // all of capability pkg are in conflict + if (_.isEmpty(maxVersion)) { + return pkgInfo[provideList[0].name]; + } + + return pkgInfo[maxVersion.name]; + } + + function _addConflicts(node) { + if (!_.isEmpty(node.conflicts)) { + _.forEach(node.conflicts, function(conflict) { + // logger.info(node.name + ' add conflict rpm : ' + conflict.name); + if (_.isEmpty(conflicts[conflict.name])) { + conflicts[conflict.name] = []; + conflicts[conflict.name].push({'name':node.name, 'data':conflict}); + } else { + conflicts[conflict.name].push({'name':node.name, 'data':conflict}); } }); + } + } - // all of capability pkg are in conflict - if (_.isEmpty(maxVersion)) { - return pkgInfo[provideList[0].name]; + function _deleteConflictData(node) { + if (!_.isEmpty(node.conflicts)) { + _.forEach(node.conflicts, function(conflict) { + if (!_.isEmpty(conflicts[conflict.name])) { + var cList = conflicts[conflict.name]; + for(var i=0; i 1) { + groupId += 1; + var groupPkgList = []; + _.forEach(sccList, function(pkg) { + pkg.group = groupId; + groupPkgList.push(pkg.name); }); + groups[groupId] = groupPkgList; + // logger.info('circular dependency: groupId(' + groupId + '), list(' + groupPkgList + ')'); + } + } + + function _createReference(node1, node2) { + if (!_.isEmpty(node1.forward) && _.includes(node1.forward, node2.name)) + return + + if (!_.isEmpty(node1.forward)) { + node1.forward.push(node2.name); + } else { + node1.forward = [node2.name]; + } + + if (!_.isEmpty(node2.backward)) { + node2.backward.push(node1.name); + } else { + node2.backward = [node1.name]; } } @@ -630,7 +862,7 @@ define([ dependents[node.name] = node; // Check for conflicts - var checkConflict = _checkConflicts(node) + var checkConflict = _checkConflicts(node, selected); if (checkConflict.result === true) { errorMsg = checkConflict.message; progressStatus = false; @@ -643,7 +875,7 @@ define([ // installation dependency analysis of package _.forEach(['requires', 'recommends'], function(depTag) { - if (_.has(node, depTag)) { + if (depTag in node) { _.forEach(node[depTag], function(require) { var choose = null; // self-reference (e.g. vim-base) @@ -651,27 +883,29 @@ define([ return; // continue } // Find dependency rpm based on capability and files - if (_.has(provides, require.name)) { - var capList = provides[require.name]; + if (require.name in provides) { if (depTag == 'requires') { - choose = _select_rpm(capList, require, node['recommends']); + choose = _select_rpm(require, selected, node['recommends']); } else { - choose = _select_rpm(capList, require); + choose = _select_rpm(require, selected, null); } - } else if (_.has(files, require.name)) { - choose = _select_files(files[require.name], require); - } else if (_.has(pkgInfo, require.name)) { + } else if (require.name in files) { + choose = _select_files(require, selected); + } else if (require.name in pkgInfo) { choose = pkgInfo[require.name]; } - if (depTag == 'recommends') { - if (!choose || (_checkConflicts(choose)).result === true) { - logger.info(require.name + ' recommended by ' + node.name + ' is ignored for selection (Conflict)'); + if (depTag === 'recommends') { + if (!choose || (_checkConflicts(choose, selected)).result === true) { + logger.info('"' + require.name + '" recommended by "' + node.name + '" is ignored for selection (Conflict)'); return; // continue } } if (choose) { + // add forward/backward reference + _createReference(node, choose); + if (selected[choose.id] === -1) { var result = _analyzeDep(choose); if (progressStatus === false) { @@ -679,7 +913,7 @@ define([ return false; } _.forEach(result, function(value, key) { - if (!_.has(dependents, key)) { + if (!(key in dependents)) { dependents[key] = value; } }); @@ -688,9 +922,6 @@ define([ // cross edge that can not be ignored min_num[pkgId] = Math.min(min_num[pkgId], min_num[choose.id]) } - - // add forward/backward reference - _createReference(node, choose); } else { // the capability does not exist. Stop dependency analysis progressStatus = false; @@ -714,7 +945,29 @@ define([ return dependents; } - var analyzeRet = _analyzeDep(checkNode); + let analyzeRet = {}; + if (!_.isEmpty(selfCheckedMap)) { + _.forEach(selfCheckedMap, function(value, key) { + if (selected[value.id] === -1) { + let instPkg = _analyzeDep(value); + if (progressStatus === true) { + _.forEach(instPkg, function(value, key){ + analyzeRet[key] = value; + }); + } else { + // TODO: remove reference + } + } + }); + } + if (!_.isEmpty(checkNode)) { + let instPkg = _analyzeDep(checkNode); + if (progressStatus === true) { + _.forEach(instPkg, function(value, key){ + analyzeRet[key] = value; + }); + } + } if (progressStatus === false) { return {'result': false, 'message': errorMsg}; } @@ -743,41 +996,25 @@ define([ for(var b=0; b because the \'' + localNode.backward + '\' packages depends on it'); - // selected node change to check state $tree.treeview('checkNode', [[node], { silent: true }]); } @@ -1070,7 +1331,6 @@ define([ pkgInfo = rawData.data.packages provides = rawData.data.provides; files = rawData.data.files; - conflicts = rawData.data.conflicts; groups = rawData.data.groups; _.forEach(groups, function(value, key) { @@ -1091,7 +1351,7 @@ define([ } } }); - _setDefaultPackage(rawData.defaultpackages); + _setDefaultPackage(rawData.installpackages); _updateSummary(); // init filter and restore checkbox state @@ -1260,17 +1520,13 @@ define([ _.forEach(pkgInfo, function(value, key) { value.checked = false; value.selfChecked = false; - value.forward = null; - value.backward = null; - value.group = null; - // INFO: bug for state.checked = false in treeview objects _.forEach(value.view, function(node) { node.state.checked = false; }); }); - groups = {}; - conflicts = {}; + selfCheckedMap = {}; + requiredInstPkgs = null; _updateSummary(); } $tree.contextmenu({