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 = [];
}
}
- 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);
}
}
- // 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<cList.length; i++) {
+ if (cList[i].name === node.name) {
+ cList.splice(i, 1);
+ break;
+ }
+ }
+ }
+ });
+ }
+ }
+
+ function _checkDependencyValidation(checkNode) {
+ let pkg_count = Object.keys(pkgInfo).length;
+ let number = 0;
+ let selected = Array.apply(null, Array(pkg_count)).map(Number.prototype.valueOf, -1);
+ let progressStatus = true;
+ let errorMsg = null;
+ let comp_rpms = {};
+ let capabilities = {};
+ let requiresRefer = {};
+
+ function _remove_dep_rpm(selectList) {
+ if (_.isEmpty(selectList)) {
+ return;
}
+ _.forEach(selectList, function(rpmInfo) {
+ selected[rpmInfo.id] = 0;
+ _deleteConflictData(rpmInfo);
+ });
+ }
- return pkgInfo[maxVersion.name];
- }
-
- function _checkConflicts(node) {
- var ret = {'result': false, 'message': 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 + ' conflict with ' + conflict.name);
- ret.message = 'The ' + node.name + ' conflict with ' + conflict.name;
- ret.result = true;
+ function _addCapabilities(node) {
+ if (_.isEmpty(node.provides)) {
+ return;
+ }
+ _.forEach(node.provides, function(pro){
+ if (!(pro.name in capabilities)) {
+ capabilities[pro.name] = [];
+ }
+ capabilities[pro.name].push(node);
+ });
+ }
+
+ function _addReference(node, require) {
+ if (!(node.name in requiresRefer)) {
+ requiresRefer[node.name] = {};
+ }
+ requiresRefer[node.name][require.name] = 1;
+ }
+
+ function _isCompatablePkg(originPkg, newPkg) {
+ let matched = true;
+ if (originPkg.name in requiresRefer) {
+ _.forEach(requiresRefer[originPkg.name], function(value, rname){
+ matched = false;
+ if (!_.isEmpty(newPkg['provides'])) {
+ _.forEach(newPkg['provides'], function(pro){
+ if (rname === pro.name) {
+ matched = true;
return false;
}
});
}
- if (ret.result === true) {
+ if (!matched && !_.isEmpty(newPkg['file'])) {
+ _.forEach(newPkg['file'], function(fname){
+ if (rname === fname) {
+ matched = true;
+ return false;
+ }
+ });
+ }
+ if(matched === false) {
+ // newPkg not compatible
return false;
}
});
}
- if (ret.result === false) {
- if (!_.isEmpty(conflicts[node.name])) {
- _.forEach(conflicts[node.name], function(conflict) {
- if (!conflict.data.ver || _meetRequiredVersion(conflict.data, node.version)) {
- // package conflict
- logger.info('[Conflict] The ' + node.name + ' conflict with ' + conflict.name);
- ret.message = 'The ' + node.name + ' conflict with ' + conflict.name;
- ret.result = true;
- return false;
- }
- });
+ return matched;
+ }
+
+ function _checkDependency(node, selectList) {
+ let pkgId = node.id;
+ number += 1;
+ selected[pkgId] = number;
+ selectList.push(node);
+
+ // add rpm's capabilities
+ _addCapabilities(node);
+
+ // Check for conflicts
+ let checkCon = _checkConflicts(node, selected)
+ if (checkCon.result === true) {
+ if (node.selfChecked === false && _isCompatablePkg(checkCon.conflictPkg, node)) {
+ logger.info('[Compatible_1] "' + node.name + '" and "' + checkCon.conflictPkg.name + '" is compatible');
+ comp_rpms[node.name] = node;
+ } else {
+ errorMsg = checkCon.message;
+ progressStatus = false;
+ return false;
}
+ } else if (!_.isEmpty(node.provides)) {
+ _.forEach(node.provides, function(pro) {
+ if (pro.name in capabilities) {
+ _.forEach(capabilities[pro.name], function(c_info) {
+ if (c_info['id'] === node['id']) {
+ return; // continue
+ }
+ if (c_info.selfChecked === false && _isCompatablePkg(c_info, node)) {
+ logger.info('[Compatible_2] "' + node.name + '" and "' + c_info.name + '" is compatible');
+ comp_rpms[node.name] = node;
+ }
+ });
+ }
+ });
}
- // 2. If the conflict package defined by node is installed
- if (ret.result === false && !_.isEmpty(node.conflicts)) {
- _.forEach(node.conflicts, function(conflict) {
- if (_.has(provides, conflict.name)) {
- _.forEach(provides[conflict.name], function(provide) {
- if (pkgInfo[provide.name].checked === true) {
- if (!conflict.ver || _meetRequiredVersion(conflict, provide.data)) {
- // package conflicts
- logger.info('[Conflict] The ' + node.name + ' conflict with ' + provide.name);
- ret.message = 'The '+node.name+'(conflicts:'+conflict.name+') conflict with '+provide.name;
- ret.result = true;
+ // add rpms into conflicts table.
+ _addConflicts(node);
+
+ // installation dependency analysis of package
+ _.forEach(['requires', 'recommends'], function(depTag) {
+ if (depTag in node) {
+ _.forEach(node[depTag], function(require) {
+ let choose = null;
+ // self-reference (e.g. vim-base)
+ if (require.name === node.name){
+ return; // continue
+ }
+ // Find dependency rpm based on capability and files
+ if (require.name in provides) {
+ if (depTag == 'requires') {
+ choose = _select_rpm(require, selected, node['recommends']);
+ } else {
+ choose = _select_rpm(require, selected, null);
+ }
+ } 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, selected)).result === true) {
+ logger.info('"' + require.name + '" recommended by "' + node.name + '" is ignored for selection (Conflict)');
+ return; // continue
+ }
+ }
+
+ if (!_.isEmpty(choose)) {
+ // add refer
+ if (depTag === 'requires') {
+ _addReference(choose, require);
+ }
+
+ if (selected[choose.id] === -1) {
+ if (_checkDependency(choose, selectList) === false) {
return false;
}
}
- });
- } else if (_.has(pkgInfo, conflict.name)) {
- var pkg = pkgInfo[conflict.name];
- if (pkg.checked === true) {
- if (!conflict.ver || _meetRequiredVersion(conflict, pkg.version)) {
- // package conflicts
- logger.info('[Conflict] The ' + node.name + ' conflit with ' + pkgInfo.name);
- ret.message = 'The '+node.name+'(conflicts:'+conflict.name+') conflict with '+pkg.name;
- ret.result = true;
- return false;
- }
+ } else {
+ // the capability does not exist. Stop dependency analysis
+ progressStatus = false;
+ errorMsg = 'The "' + require.name + '" needed by "' + node.name + '" does not exist. Please check the repository';
+ logger.info('###' + errorMsg);
+ return false;
}
- }
- if (ret.result === true) {
- return false;
- }
- });
+ });
+ }
+ if (progressStatus === false) {
+ // Stop dependency analysis
+ return false;
+ }
+ });
+ return progressStatus;
+ }
+
+ // global variable (Reference object for rpm selection)
+ conflicts = {};
+ requiredInstPkgs = {};
+ _.forEach(selfCheckedMap, function(value, key){
+ requiredInstPkgs[key] = value;
+ });
+ let selectList;
+ _.forEach(selfCheckedMap, function(node, key) {
+ if (selected[node.id] === -1) {
+ selectList = [];
+ progressStatus = true;
+ if (_checkDependency(node, selectList)) {
+ comp_rpms[node.name] = node;
+ } else {
+ _remove_dep_rpm(selectList);
+ logger.info('###ERROR### The "' + node.name + '" does not selected')
+ }
+ } else {
+ comp_rpms[node.name] = node;
+ }
+ });
+ selectList = [];
+ if (!_.isEmpty(checkNode)) {
+ if (_checkDependency(checkNode, selectList)) {
+ comp_rpms[checkNode.name] = checkNode;
}
- return ret;
}
- 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});
- }
+ if (progressStatus === false) {
+ return {'result': false, 'message': errorMsg};
+ }
+ return {'result': true, 'data': comp_rpms};
+ }
+
+ function _resetRerferenceInfo() {
+ _.forEach(pkgInfo, function(value, key) {
+ value['backward'] = null;
+ value['forward'] = null;
+ value['group'] = null;
+ });
+ }
+
+ // analyze install-dependency (requires)
+ function _analyzeInstallDependency(checkNode, requiredPkgs) {
+ let stack = [];
+ let pkg_count = Object.keys(pkgInfo).length
+ let number = 0;
+ let sccNum = 0;
+ let groupNum = 0;
+ let selected = Array.apply(null, Array(pkg_count)).map(Number.prototype.valueOf, -1);
+ let scc_id = Array.apply(null, Array(pkg_count)).map(Number.prototype.valueOf, 0);
+ let min_num = new Array(pkg_count);
+ let progressStatus = true;
+ let errorMsg = null;
+ let conflictsTable = {};
+
+ // global variable (Reference object for rpm selection)
+ conflicts = {};
+ requiredInstPkgs = {};
+ _.forEach(requiredPkgs, function(value, key){
+ requiredInstPkgs[key] = value;
+ });
+ _resetRerferenceInfo();
+
+ // 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;
+ }
+ }
+
+ // 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 + ')');
+ }
+ }
+
+ 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];
}
}
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;
// 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)
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) {
return false;
}
_.forEach(result, function(value, key) {
- if (!_.has(dependents, key)) {
+ if (!(key in dependents)) {
dependents[key] = value;
}
});
// 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;
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};
}
for(var b=0; b<pkg.backward.length; b++) {
// If node is Referenced by another node (Not a node in the group),
// unable to uncheck group nodes
- if (!_.has(groupObj, pkg.backward[b])) {
+ if (!(pkg.backward[b] in groupObj)) {
return false;
}
}
}
// init visited obj
- groupVisited[groupId] = {};
+ // groupVisited[groupId] = {};
// Delete backward reference of group node
- _.forEach(groupPkgList, function(pkgName) {
- var pkg = _find(pkgName);
- // backward ref.
- pkg.backward = null;
- // visited init
- groupVisited[groupId][pkg.name] = -1;
- });
+ // _.forEach(groupPkgList, function(pkgName) {
+ // var pkg = _find(pkgName);
+ // // backward ref.
+ // pkg.backward = null;
+ // // visited init
+ // groupVisited[groupId][pkg.name] = -1;
+ // });
//logger.info('Group(' + groupId + ') is uncheckable : ' + groupPkgList);
return true;
}
- 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<cList.length; i++) {
- if (cList[i].name === node.name) {
- cList.splice(i, 1);
- break;
- }
- }
- }
- });
- }
- }
-
function _analyzeUncheck(parent, node) {
if (!_.isEmpty(parent)) {
// TODO: performance
// updates pkgs for uncheck
if (!_.isEmpty(result)) {
_.forEach(result, function(value, key) {
- if (!_.has(uncheckPkgs, key)) {
+ if (!(key in uncheckPkgs)) {
uncheckPkgs[key] = value;
}
});
node.forward = null;
node.group = null;
}
-
+
// delete conflict data from conflicts table
- _deleteConflictData(node);
+ // _deleteConflictData(node);
return uncheckPkgs;
}
// { 'group_id' : {pkgName: -1, ... }, ... }
- var groupVisited = {};
- var uncheckPkgs = _analyzeUncheck(null, uncheckNode);
+ // var groupVisited = {};
+ // var uncheckPkgs = _analyzeUncheck(null, uncheckNode);
// delete groupId from groups
- _.forEach(groupVisited, function(groupList, groupId) {
- if (!_.isEmpty(groups[groupId])) {
- delete groups[groupId];
+ // _.forEach(groupVisited, function(groupList, groupId) {
+ // if (!_.isEmpty(groups[groupId])) {
+ // delete groups[groupId];
+ // }
+ // });
+ // return uncheckPkgs;
+ if (!_.isEmpty(uncheckNode.backward)) {
+ // check circular dependency
+ if (!uncheckNode.group || !_checkCircularDependency(uncheckNode)) {
+ return false;
}
- });
-
- return uncheckPkgs;
+ }
+ return true;
}
/**
}
}
+ function reverseCheckAndAlert(message, pkgNode, viewNode, check) {
+ Util.showAlertDialog(message);
+ pkgNode.checked = check;
+ let toggleNodes = [];
+ if(check === true) {
+ $tree.treeview('checkNode', [[viewNode], { silent: true }]);
+ } else {
+ $tree.treeview('uncheckNode', [[viewNode], { silent: true }]);
+ }
+ }
+
+ function _checkDependencyPackages(dendencyPkgs) {
+ let checkNodes = [];
+ let uncheckNodes = [];
+ _.forEach(pkgInfo, function(node, pkgName){
+ if(pkgName in dendencyPkgs) {
+ node['checked'] = true;
+ // check node
+ _.forEach(node.view, function(vnode) {
+ if (vnode.state.checked === false) {
+ checkNodes.push(vnode);
+ }
+ });
+ } else {
+ if (!_.isEmpty(node)){
+ // uncheck node
+ node['checked'] = false;
+ _.forEach(node.view, function(vnode) {
+ if (vnode.state.checked === true) {
+ uncheckNodes.push(vnode);
+ }
+ });
+ } else {
+ logger.info(pkgName);
+ }
+ }
+ });
+ $tree.treeview('checkNode', [checkNodes, { silent: true }]);
+ $tree.treeview('uncheckNode', [uncheckNodes, { silent: true }]);
+ }
+
/**
* Treeview: A node is checked.
*/
function _onNodeChecked(event, node) {
- var startTS = performance.now();
- var localNode = _findFromNode(node);
+ let startTS = performance.now();
+ let localNode = _findFromNode(node);
if (_.isEmpty(localNode)) {
// MISC is virtual pacakge.
logger.info('[Check] checked: ' + localNode.name);
_nodeSelected(event, node);
-
$tree.treeview('expandNode', [node, { silent: false }]);
localNode.selfChecked = true;
- var depResult = _analyzeInstallDependency(localNode)
+ // 1. pre-dependency analysis
+ let rpmcheck = _checkDependencyValidation(localNode);
+ if (rpmcheck.result === false) {
+ localNode.selfChecked = false;
+ reverseCheckAndAlert(rpmcheck.message, localNode, node, false);
+ return;
+ }
+ let depResult = _analyzeInstallDependency(localNode, rpmcheck.data);
// Removing all references because the node can not be checked
// Case: conflicts, rpm does not exist...
if (depResult.result === false) {
- Util.showAlertDialog(depResult.message);
- localNode.checked = true;
- $tree.treeview('uncheckNode', [node, { silent: false }]);
+ localNode.selfChecked = false;
+ reverseCheckAndAlert(depResult.message, localNode, node, false);
+ return;
}
- var analyzeTS = performance.now();
-
- // TODO: debug code (should be deleted)
- // var tempcode = [];
- // _.forEach(depPkg, function(value, key) { tempcode.push(value.name); });
- // logger.info(localNode.name + ' install-dependency(' + tempcode.length +'): ' + tempcode);
-
- var toggleNode = [];
- if (!_.isEmpty(depResult.data)) {
- _.forEach(depResult.data, function(value, key) {
- // update local data
- value.checked = true;
- // update treeview data
- _.forEach(value.view, function(node) {
- if (node.state.checked === false) {
- toggleNode.push(node);
- }
- });
- });
-
- $tree.treeview('checkNode', [toggleNode, { silent: true }]);
- _updateSummary();
-
- var endTS = performance.now();
- logger.info('[Check] Total time: ' + (endTS - startTS) + 'ms');
- logger.info('[Check] Analyze dep. time: ' + (analyzeTS - startTS) + 'ms');
- logger.info('[Check] Update view time: ' + (endTS - analyzeTS) + 'ms');
- }
+ let analyzeTS = performance.now();
+ selfCheckedMap[localNode.name] = localNode;
+ _checkDependencyPackages(depResult.data)
+ _updateSummary();
+ var endTS = performance.now();
+ logger.info('[Check] Total time: ' + (endTS - startTS) + 'ms');
+ logger.info('[Check] Analyze dep. time: ' + (analyzeTS - startTS) + 'ms');
+ logger.info('[Check] Update view time: ' + (endTS - analyzeTS) + 'ms');
}
/**
}
logger.info('unchecked: ' + node.text);
-
- var uncheckPkgs = _analyzeUncheckDependency(localNode);
-
- var analyzeTS = performance.now();
-
- // TODO: debug code (should be deleted)
- // var tempcode = [];
- // _.forEach(uncheckPkgs, function(value, key) { tempcode.push(value.name); });
- // logger.info(localNode.name + ' uncheck-dependency(' + tempcode.length +'): ' + tempcode);
-
- var toggleNode = [];
- if (!_.isEmpty(uncheckPkgs)) {
- _.forEach(uncheckPkgs, function(value, key) {
- // update local data
- value.checked = false;
- // update treeview data
- _.forEach(value.view, function(node) {
- if (node.state.checked === true) {
- toggleNode.push(node);
- }
- });
- });
-
- $tree.treeview('uncheckNode', [toggleNode, { silent: true }]);
+ if (_analyzeUncheckDependency(localNode)) {
localNode.selfChecked = false;
+ delete selfCheckedMap[localNode.name];
+
+ // 1. pre-dependency analysis
+ let rpmcheck = _checkDependencyValidation(null);
+ if (rpmcheck.result === false) {
+ reverseCheckAndAlert(depResult.message, localNode, node, false);
+ return;
+ }
+ let depResult = _analyzeInstallDependency(null, rpmcheck.data);
+ if (depResult.result === false) {
+ reverseCheckAndAlert(depResult.message, localNode, node, false);
+ return;
+ }
+ var analyzeTS = performance.now();
+ _checkDependencyPackages(depResult.data);
_updateSummary();
} else {
Util.showAlertDialog('Could not uncheck the \'' +localNode.name + '\'' + '<br> because the \'' + localNode.backward + '\' packages depends on it');
-
// selected node change to check state
$tree.treeview('checkNode', [[node], { silent: true }]);
}
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) {
}
}
});
- _setDefaultPackage(rawData.defaultpackages);
+ _setDefaultPackage(rawData.installpackages);
_updateSummary();
// init filter and restore checkbox state
_.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({